blob: 6feb710fa276608c203f2b0783c29b39118ae0b5 [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 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 Wasilczyk213170b2017-02-07 17:38:21 -080025#include <android-base/logging.h>
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070026#include <broadcastradio-utils/Utils.h>
27#include <broadcastradio-vts-utils/call-barrier.h>
28#include <broadcastradio-vts-utils/mock-timeout.h>
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080029#include <cutils/native_handle.h>
30#include <cutils/properties.h>
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070031#include <gmock/gmock.h>
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080032#include <hidl/HidlTransportSupport.h>
33#include <utils/threads.h>
34
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070035#include <chrono>
36
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070037namespace android {
38namespace hardware {
39namespace broadcastradio {
40namespace V1_1 {
41namespace vts {
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080042
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070043using namespace std::chrono_literals;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080044
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070045using testing::_;
46using testing::AnyNumber;
47using testing::ByMove;
48using testing::DoAll;
Tomasz Wasilczyk24180092017-07-14 10:44:52 -070049using testing::Invoke;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070050using testing::SaveArg;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080051
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070052using broadcastradio::vts::CallBarrier;
53using V1_0::BandConfig;
54using V1_0::Class;
55using V1_0::MetaData;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -070056using V1_0::MetadataKey;
57using V1_0::MetadataType;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080058
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070059using std::chrono::steady_clock;
60using std::this_thread::sleep_for;
61
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
72static constexpr IdentifierType kVendorPrimartIds[] = {
73 IdentifierType::VENDOR1_PRIMARY, IdentifierType::VENDOR2_PRIMARY,
74 IdentifierType::VENDOR3_PRIMARY, IdentifierType::VENDOR4_PRIMARY};
75
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070076static void printSkipped(std::string msg) {
77 std::cout << "[ SKIPPED ] " << msg << std::endl;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080078}
79
Tomasz Wasilczyk24180092017-07-14 10:44:52 -070080struct TunerCallbackMock : public ITunerCallback {
81 TunerCallbackMock() { EXPECT_CALL(*this, hardwareFailure()).Times(0); }
82
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070083 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&));
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -070086 MOCK_TIMEOUT_METHOD2(tuneComplete_1_1, Return<void>(Result, const ProgramSelector&));
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070087 MOCK_METHOD1(afSwitch, Return<void>(const V1_0::ProgramInfo&));
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -070088 MOCK_METHOD1(afSwitch_1_1, Return<void>(const ProgramSelector&));
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070089 MOCK_METHOD1(antennaStateChange, Return<void>(bool connected));
90 MOCK_METHOD1(trafficAnnouncement, Return<void>(bool active));
91 MOCK_METHOD1(emergencyAnnouncement, Return<void>(bool active));
92 MOCK_METHOD3(newMetadata, Return<void>(uint32_t ch, uint32_t subCh, const hidl_vec<MetaData>&));
93 MOCK_METHOD1(backgroundScanAvailable, Return<void>(bool));
94 MOCK_TIMEOUT_METHOD1(backgroundScanComplete, Return<void>(ProgramListResult));
95 MOCK_METHOD0(programListChanged, Return<void>());
Tomasz Wasilczykdd587702017-07-31 14:28:04 -070096 MOCK_TIMEOUT_METHOD0(currentProgramInfoChanged, Return<void>());
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070097};
98
99class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
100 public ::testing::WithParamInterface<Class> {
101 protected:
102 virtual void SetUp() override;
103 virtual void TearDown() override;
104
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700105 bool openTuner();
106 bool nextBand();
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700107 bool getProgramList(std::function<void(const hidl_vec<ProgramInfo>& list)> cb);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700108
109 Class radioClass;
110 bool skipped = false;
111
112 sp<IBroadcastRadio> mRadioModule;
113 sp<ITuner> mTuner;
114 sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
115
116 private:
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700117 const BandConfig& getBand(unsigned idx);
118
119 unsigned currentBandIndex = 0;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700120 hidl_vec<BandConfig> mBands;
121};
122
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700123/**
124 * Clears strong pointer and waits until the object gets destroyed.
125 *
126 * @param ptr The pointer to get cleared.
127 * @param timeout Time to wait for other references.
128 */
129template <typename T>
130static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
131 wp<T> wptr = ptr;
132 ptr.clear();
133 auto limit = steady_clock::now() + timeout;
134 while (wptr.promote() != nullptr) {
135 constexpr auto step = 10ms;
136 if (steady_clock::now() + step > limit) {
137 FAIL() << "Pointer was not released within timeout";
138 break;
139 }
140 sleep_for(step);
141 }
142}
143
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700144void BroadcastRadioHalTest::SetUp() {
145 radioClass = GetParam();
146
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700147 // lookup HIDL service
148 auto factory = getService<IBroadcastRadioFactory>();
149 ASSERT_NE(nullptr, factory.get());
150
151 // connect radio module
152 Result connectResult;
153 CallBarrier onConnect;
154 factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
155 connectResult = ret;
156 if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
157 onConnect.call();
158 });
159 ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
160
161 if (connectResult == Result::INVALID_ARGUMENTS) {
162 printSkipped("This device class is not supported.");
163 skipped = true;
164 return;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800165 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700166 ASSERT_EQ(connectResult, Result::OK);
167 ASSERT_NE(nullptr, mRadioModule.get());
168
169 // get module properties
170 Properties prop11;
171 auto& prop10 = prop11.base;
172 auto propResult =
173 mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
174
175 ASSERT_TRUE(propResult.isOk());
176 EXPECT_EQ(radioClass, prop10.classId);
177 EXPECT_GT(prop10.numTuners, 0u);
Tomasz Wasilczyke192c392017-07-16 15:14:34 -0700178 EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
179 EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700180 if (radioClass == Class::AM_FM) {
181 EXPECT_GT(prop10.bands.size(), 0u);
182 }
183 mBands = prop10.bands;
184}
185
186void BroadcastRadioHalTest::TearDown() {
187 mTuner.clear();
188 mRadioModule.clear();
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700189 clearAndWait(mCallback, 1s);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700190}
191
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700192bool BroadcastRadioHalTest::openTuner() {
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700193 EXPECT_EQ(nullptr, mTuner.get());
194
195 if (radioClass == Class::AM_FM) {
196 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
197 }
198
199 Result halResult = Result::NOT_INITIALIZED;
200 auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
201 halResult = result;
202 if (result != Result::OK) return;
203 mTuner = ITuner::castFrom(tuner);
204 };
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700205 currentBandIndex = 0;
206 auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700207
208 EXPECT_TRUE(hidlResult.isOk());
209 EXPECT_EQ(Result::OK, halResult);
210 EXPECT_NE(nullptr, mTuner.get());
211 if (radioClass == Class::AM_FM && mTuner != nullptr) {
212 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
213
214 BandConfig halConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800215 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700216 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
217 halResult = result;
218 halConfig = config;
219 });
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800220 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700221 EXPECT_TRUE(halConfig.antennaConnected);
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800222 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700223
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800224 EXPECT_NE(nullptr, mTuner.get());
225 return nullptr != mTuner.get();
226}
227
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700228const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
229 static const BandConfig dummyBandConfig = {};
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800230
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700231 if (radioClass != Class::AM_FM) {
232 ALOGD("Not AM/FM radio, returning dummy band config");
233 return dummyBandConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800234 }
235
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700236 EXPECT_GT(mBands.size(), idx);
237 if (mBands.size() <= idx) {
238 ALOGD("Band index out of bound, returning dummy band config");
239 return dummyBandConfig;
240 }
241
242 auto& band = mBands[idx];
243 ALOGD("Returning %s band", toString(band.type).c_str());
244 return band;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800245}
246
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700247bool BroadcastRadioHalTest::nextBand() {
248 if (currentBandIndex + 1 >= mBands.size()) return false;
249 currentBandIndex++;
250
251 BandConfig bandCb;
252 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
253 .WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
254 auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
255 EXPECT_EQ(Result::OK, hidlResult);
256 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
257 EXPECT_EQ(getBand(currentBandIndex), bandCb);
258
259 return true;
260}
261
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700262bool BroadcastRadioHalTest::getProgramList(
263 std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
264 ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
265 bool isListEmpty = true;
266 auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
267 ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
268 getListResult = result;
269 if (result != ProgramListResult::OK) return;
270 isListEmpty = (list.size() == 0);
271 if (!isListEmpty) cb(list);
272 };
273
274 // first try...
275 EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
276 .Times(AnyNumber());
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700277 auto hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700278 EXPECT_TRUE(hidlResult.isOk());
279 if (!hidlResult.isOk()) return false;
280
281 if (getListResult == ProgramListResult::NOT_STARTED) {
282 auto result = mTuner->startBackgroundScan();
283 EXPECT_EQ(ProgramListResult::OK, result);
284 getListResult = ProgramListResult::NOT_READY; // continue as in NOT_READY case
285 }
286 if (getListResult == ProgramListResult::NOT_READY) {
287 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
288
289 // second (last) try...
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700290 hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700291 EXPECT_TRUE(hidlResult.isOk());
292 if (!hidlResult.isOk()) return false;
293 EXPECT_EQ(ProgramListResult::OK, getListResult);
294 }
295
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700296 return !isListEmpty;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700297}
298
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700299/**
300 * Test IBroadcastRadio::openTuner() method called twice.
301 *
302 * Verifies that:
303 * - the openTuner method succeeds when called for the second time without
304 * deleting previous ITuner instance.
305 *
306 * This is a more strict requirement than in 1.0, where a second openTuner
307 * might fail.
308 */
309TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
310 if (skipped) return;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700311
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700312 ASSERT_TRUE(openTuner());
313
314 auto secondTuner = mTuner;
315 mTuner.clear();
316
317 ASSERT_TRUE(openTuner());
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700318}
319
320/**
321 * Test tuning to program list entry.
322 *
323 * Verifies that:
324 * - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
325 * - if the program list is NOT_STARTED, startBackgroundScan makes it completed
326 * within a full scan timeout and the next getProgramList call succeeds;
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700327 * - if the program list is not empty, tuneByProgramSelector call succeeds;
328 * - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700329 */
330TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
331 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700332 ASSERT_TRUE(openTuner());
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700333
334 ProgramInfo firstProgram;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700335 bool foundAny = false;
336 do {
337 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
338 // don't copy the whole list out, it might be heavy
339 firstProgram = list[0];
340 };
341 if (getProgramList(getCb)) foundAny = true;
342 } while (nextBand());
343 if (HasFailure()) return;
344 if (!foundAny) {
345 printSkipped("Program list is empty.");
346 return;
347 }
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700348
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700349 ProgramSelector selCb;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700350 EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700351 EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700352 .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700353 EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged);
Tomasz Wasilczykb8a2afe2017-08-01 10:52:18 -0700354 auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700355 ASSERT_EQ(Result::OK, tuneResult);
356 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700357 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700358 EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700359
360 bool called = false;
361 auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
362 called = true;
363 EXPECT_EQ(Result::OK, result);
364 EXPECT_EQ(selCb, info.selector);
365 });
366 ASSERT_TRUE(getResult.isOk());
367 ASSERT_TRUE(called);
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700368}
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800369
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700370/**
371 * Test that primary vendor identifier isn't used for standard program types.
372 *
373 * Verifies that:
374 * - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
375 * identifier for program types other than VENDORn.
376 */
377TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
378 if (skipped) return;
379 ASSERT_TRUE(openTuner());
380
381 for (auto ptype : kStandardProgramTypes) {
382 ALOGD("Checking %s...", toString(ptype).c_str());
383 for (auto idtype : kVendorPrimartIds) {
384 ALOGD("...with %s", toString(idtype).c_str());
385 ProgramSelector sel = {};
386 sel.programType = static_cast<uint32_t>(ptype);
387 sel.primaryId.type = static_cast<uint32_t>(idtype);
388
389 auto tuneResult = mTuner->tuneByProgramSelector(sel);
390 ASSERT_NE(Result::OK, tuneResult);
391 }
392 }
393}
394
395/**
396 * Test that tune with unknown program type fails.
397 *
398 * Verifies that:
399 * - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
400 */
401TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
402 if (skipped) return;
403 ASSERT_TRUE(openTuner());
404
405 // Program type is 1-based, so 0 will be always invalid.
406 ProgramSelector sel = {};
407 auto tuneResult = mTuner->tuneByProgramSelector(sel);
408 ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
409}
410
411/**
412 * Test cancelling announcement.
413 *
414 * Verifies that:
415 * - cancelAnnouncement succeeds either when there is an announcement or there is none.
416 */
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700417TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
418 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700419 ASSERT_TRUE(openTuner());
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700420
421 auto hidlResult = mTuner->cancelAnnouncement();
422 EXPECT_EQ(Result::OK, hidlResult);
423}
424
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700425/**
426 * Test getImage call with invalid image ID.
427 *
428 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700429 * - getImage call handles argument 0 gracefully.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700430 */
431TEST_P(BroadcastRadioHalTest, GetNoImage) {
432 if (skipped) return;
433
434 size_t len = 0;
435 auto hidlResult =
436 mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
437
438 ASSERT_TRUE(hidlResult.isOk());
439 ASSERT_EQ(0u, len);
440}
441
442/**
443 * Test proper image format in metadata.
444 *
445 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700446 * - all images in metadata are provided out-of-band (by id, not as a binary blob);
447 * - images are available for getImage call.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700448 */
449TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
450 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700451 ASSERT_TRUE(openTuner());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700452
453 std::vector<int> imageIds;
454
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700455 do {
456 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
457 for (auto&& program : list) {
458 for (auto&& entry : program.base.metadata) {
459 EXPECT_NE(MetadataType::RAW, entry.type);
460 if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
461 EXPECT_NE(0, entry.intValue);
462 EXPECT_EQ(0u, entry.rawValue.size());
463 if (entry.intValue != 0) imageIds.push_back(entry.intValue);
464 }
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700465 }
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700466 };
467 getProgramList(getCb);
468 } while (nextBand());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700469
470 if (imageIds.size() == 0) {
471 printSkipped("No images found");
472 return;
473 }
474
475 for (auto id : imageIds) {
476 ALOGD("Checking image %d", id);
477
478 size_t len = 0;
479 auto hidlResult =
480 mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
481
482 ASSERT_TRUE(hidlResult.isOk());
483 ASSERT_GT(len, 0u);
484 }
485}
486
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700487/**
488 * Test AnalogForced switch.
489 *
490 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700491 * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700492 */
493TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
494 if (skipped) return;
495 ASSERT_TRUE(openTuner());
496
497 bool forced;
498 Result halIsResult;
499 auto isCb = [&](Result result, bool isForced) {
500 halIsResult = result;
501 forced = isForced;
502 };
503
504 // set analog mode
505 auto setResult = mTuner->setAnalogForced(true);
506 ASSERT_TRUE(setResult.isOk());
507 if (Result::INVALID_STATE == setResult) {
508 // if setter fails, getter should fail too - it means the switch is not supported at all
509 auto isResult = mTuner->isAnalogForced(isCb);
510 ASSERT_TRUE(isResult.isOk());
511 EXPECT_EQ(Result::INVALID_STATE, halIsResult);
512 return;
513 }
514 ASSERT_EQ(Result::OK, setResult);
515
516 // check, if it's analog
517 auto isResult = mTuner->isAnalogForced(isCb);
518 ASSERT_TRUE(isResult.isOk());
519 EXPECT_EQ(Result::OK, halIsResult);
520 ASSERT_TRUE(forced);
521
522 // set digital mode
523 setResult = mTuner->setAnalogForced(false);
524 ASSERT_EQ(Result::OK, setResult);
525
526 // check, if it's digital
527 isResult = mTuner->isAnalogForced(isCb);
528 ASSERT_TRUE(isResult.isOk());
529 EXPECT_EQ(Result::OK, halIsResult);
530 ASSERT_FALSE(forced);
531}
532
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700533INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
534 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
535
536} // namespace vts
537} // namespace V1_1
538} // namespace broadcastradio
539} // namespace hardware
540} // namespace android
541
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800542int main(int argc, char** argv) {
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800543 ::testing::InitGoogleTest(&argc, argv);
544 int status = RUN_ALL_TESTS();
545 ALOGI("Test result = %d", status);
546 return status;
547}