blob: a46378ee6af64783f7805f0cfaed0cdc1a6cd022 [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
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
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700118/**
119 * Clears strong pointer and waits until the object gets destroyed.
120 *
121 * @param ptr The pointer to get cleared.
122 * @param timeout Time to wait for other references.
123 */
124template <typename T>
125static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
126 wp<T> wptr = ptr;
127 ptr.clear();
128 auto limit = steady_clock::now() + timeout;
129 while (wptr.promote() != nullptr) {
130 constexpr auto step = 10ms;
131 if (steady_clock::now() + step > limit) {
132 FAIL() << "Pointer was not released within timeout";
133 break;
134 }
135 sleep_for(step);
136 }
137}
138
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700139void BroadcastRadioHalTest::SetUp() {
140 radioClass = GetParam();
141
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700142 // lookup HIDL service
143 auto factory = getService<IBroadcastRadioFactory>();
144 ASSERT_NE(nullptr, factory.get());
145
146 // connect radio module
147 Result connectResult;
148 CallBarrier onConnect;
149 factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
150 connectResult = ret;
151 if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
152 onConnect.call();
153 });
154 ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
155
156 if (connectResult == Result::INVALID_ARGUMENTS) {
157 printSkipped("This device class is not supported.");
158 skipped = true;
159 return;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800160 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700161 ASSERT_EQ(connectResult, Result::OK);
162 ASSERT_NE(nullptr, mRadioModule.get());
163
164 // get module properties
165 Properties prop11;
166 auto& prop10 = prop11.base;
167 auto propResult =
168 mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
169
170 ASSERT_TRUE(propResult.isOk());
171 EXPECT_EQ(radioClass, prop10.classId);
172 EXPECT_GT(prop10.numTuners, 0u);
Tomasz Wasilczyke192c392017-07-16 15:14:34 -0700173 EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
174 EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700175 if (radioClass == Class::AM_FM) {
176 EXPECT_GT(prop10.bands.size(), 0u);
177 }
178 mBands = prop10.bands;
179}
180
181void BroadcastRadioHalTest::TearDown() {
182 mTuner.clear();
183 mRadioModule.clear();
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700184 clearAndWait(mCallback, 1s);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700185}
186
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700187bool BroadcastRadioHalTest::openTuner() {
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700188 EXPECT_EQ(nullptr, mTuner.get());
189
190 if (radioClass == Class::AM_FM) {
191 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
192 }
193
194 Result halResult = Result::NOT_INITIALIZED;
195 auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
196 halResult = result;
197 if (result != Result::OK) return;
198 mTuner = ITuner::castFrom(tuner);
199 };
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700200 currentBandIndex = 0;
201 auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700202
203 EXPECT_TRUE(hidlResult.isOk());
204 EXPECT_EQ(Result::OK, halResult);
205 EXPECT_NE(nullptr, mTuner.get());
206 if (radioClass == Class::AM_FM && mTuner != nullptr) {
207 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
208
209 BandConfig halConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800210 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700211 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
212 halResult = result;
213 halConfig = config;
214 });
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800215 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700216 EXPECT_TRUE(halConfig.antennaConnected);
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800217 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700218
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800219 EXPECT_NE(nullptr, mTuner.get());
220 return nullptr != mTuner.get();
221}
222
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700223const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
224 static const BandConfig dummyBandConfig = {};
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800225
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700226 if (radioClass != Class::AM_FM) {
227 ALOGD("Not AM/FM radio, returning dummy band config");
228 return dummyBandConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800229 }
230
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700231 EXPECT_GT(mBands.size(), idx);
232 if (mBands.size() <= idx) {
233 ALOGD("Band index out of bound, returning dummy band config");
234 return dummyBandConfig;
235 }
236
237 auto& band = mBands[idx];
238 ALOGD("Returning %s band", toString(band.type).c_str());
239 return band;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800240}
241
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700242bool BroadcastRadioHalTest::nextBand() {
243 if (currentBandIndex + 1 >= mBands.size()) return false;
244 currentBandIndex++;
245
246 BandConfig bandCb;
247 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
248 .WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
249 auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
250 EXPECT_EQ(Result::OK, hidlResult);
251 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
252 EXPECT_EQ(getBand(currentBandIndex), bandCb);
253
254 return true;
255}
256
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700257bool BroadcastRadioHalTest::getProgramList(
258 std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
259 ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
260 bool isListEmpty = true;
261 auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
262 ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
263 getListResult = result;
264 if (result != ProgramListResult::OK) return;
265 isListEmpty = (list.size() == 0);
266 if (!isListEmpty) cb(list);
267 };
268
269 // first try...
270 EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
271 .Times(AnyNumber());
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700272 auto hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700273 EXPECT_TRUE(hidlResult.isOk());
274 if (!hidlResult.isOk()) return false;
275
276 if (getListResult == ProgramListResult::NOT_STARTED) {
277 auto result = mTuner->startBackgroundScan();
278 EXPECT_EQ(ProgramListResult::OK, result);
279 getListResult = ProgramListResult::NOT_READY; // continue as in NOT_READY case
280 }
281 if (getListResult == ProgramListResult::NOT_READY) {
282 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
283
284 // second (last) try...
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700285 hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700286 EXPECT_TRUE(hidlResult.isOk());
287 if (!hidlResult.isOk()) return false;
288 EXPECT_EQ(ProgramListResult::OK, getListResult);
289 }
290
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700291 return !isListEmpty;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700292}
293
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700294/**
295 * Test IBroadcastRadio::openTuner() method called twice.
296 *
297 * Verifies that:
298 * - the openTuner method succeeds when called for the second time without
299 * deleting previous ITuner instance.
300 *
301 * This is a more strict requirement than in 1.0, where a second openTuner
302 * might fail.
303 */
304TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
305 if (skipped) return;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700306
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700307 ASSERT_TRUE(openTuner());
308
309 auto secondTuner = mTuner;
310 mTuner.clear();
311
312 ASSERT_TRUE(openTuner());
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700313}
314
315/**
316 * Test tuning to program list entry.
317 *
318 * Verifies that:
319 * - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
320 * - if the program list is NOT_STARTED, startBackgroundScan makes it completed
321 * within a full scan timeout and the next getProgramList call succeeds;
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700322 * - if the program list is not empty, tuneByProgramSelector call succeeds;
323 * - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700324 */
325TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
326 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700327 ASSERT_TRUE(openTuner());
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700328
329 ProgramInfo firstProgram;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700330 bool foundAny = false;
331 do {
332 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
333 // don't copy the whole list out, it might be heavy
334 firstProgram = list[0];
335 };
336 if (getProgramList(getCb)) foundAny = true;
337 } while (nextBand());
338 if (HasFailure()) return;
339 if (!foundAny) {
340 printSkipped("Program list is empty.");
341 return;
342 }
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700343
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700344 ProgramInfo infoCb;
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700345 ProgramSelector selCb;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700346 EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700347 EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700348 .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700349 EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged, _)
350 .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
Tomasz Wasilczykb8a2afe2017-08-01 10:52:18 -0700351 auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700352 ASSERT_EQ(Result::OK, tuneResult);
353 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700354 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700355 EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700356 EXPECT_EQ(infoCb.selector, selCb);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700357
358 bool called = false;
359 auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
360 called = true;
361 EXPECT_EQ(Result::OK, result);
362 EXPECT_EQ(selCb, info.selector);
363 });
364 ASSERT_TRUE(getResult.isOk());
365 ASSERT_TRUE(called);
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700366}
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800367
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700368/**
369 * Test that primary vendor identifier isn't used for standard program types.
370 *
371 * Verifies that:
372 * - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
373 * identifier for program types other than VENDORn.
374 */
375TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
376 if (skipped) return;
377 ASSERT_TRUE(openTuner());
378
379 for (auto ptype : kStandardProgramTypes) {
380 ALOGD("Checking %s...", toString(ptype).c_str());
Tomasz Wasilczykda97a6d2017-08-04 12:57:29 -0700381 ProgramSelector sel = {};
382 sel.programType = static_cast<uint32_t>(ptype);
383 sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700384
Tomasz Wasilczykda97a6d2017-08-04 12:57:29 -0700385 auto tuneResult = mTuner->tuneByProgramSelector(sel);
386 ASSERT_NE(Result::OK, tuneResult);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700387 }
388}
389
390/**
391 * Test that tune with unknown program type fails.
392 *
393 * Verifies that:
394 * - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
395 */
396TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
397 if (skipped) return;
398 ASSERT_TRUE(openTuner());
399
400 // Program type is 1-based, so 0 will be always invalid.
401 ProgramSelector sel = {};
402 auto tuneResult = mTuner->tuneByProgramSelector(sel);
403 ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
404}
405
406/**
407 * Test cancelling announcement.
408 *
409 * Verifies that:
410 * - cancelAnnouncement succeeds either when there is an announcement or there is none.
411 */
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700412TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
413 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700414 ASSERT_TRUE(openTuner());
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700415
416 auto hidlResult = mTuner->cancelAnnouncement();
417 EXPECT_EQ(Result::OK, hidlResult);
418}
419
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700420/**
421 * Test getImage call with invalid image ID.
422 *
423 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700424 * - getImage call handles argument 0 gracefully.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700425 */
426TEST_P(BroadcastRadioHalTest, GetNoImage) {
427 if (skipped) return;
428
429 size_t len = 0;
430 auto hidlResult =
431 mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
432
433 ASSERT_TRUE(hidlResult.isOk());
434 ASSERT_EQ(0u, len);
435}
436
437/**
438 * Test proper image format in metadata.
439 *
440 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700441 * - all images in metadata are provided out-of-band (by id, not as a binary blob);
442 * - images are available for getImage call.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700443 */
444TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
445 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700446 ASSERT_TRUE(openTuner());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700447
448 std::vector<int> imageIds;
449
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700450 do {
451 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
452 for (auto&& program : list) {
453 for (auto&& entry : program.base.metadata) {
454 EXPECT_NE(MetadataType::RAW, entry.type);
455 if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
456 EXPECT_NE(0, entry.intValue);
457 EXPECT_EQ(0u, entry.rawValue.size());
458 if (entry.intValue != 0) imageIds.push_back(entry.intValue);
459 }
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700460 }
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700461 };
462 getProgramList(getCb);
463 } while (nextBand());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700464
465 if (imageIds.size() == 0) {
466 printSkipped("No images found");
467 return;
468 }
469
470 for (auto id : imageIds) {
471 ALOGD("Checking image %d", id);
472
473 size_t len = 0;
474 auto hidlResult =
475 mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
476
477 ASSERT_TRUE(hidlResult.isOk());
478 ASSERT_GT(len, 0u);
479 }
480}
481
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700482/**
483 * Test AnalogForced switch.
484 *
485 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700486 * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700487 */
488TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
489 if (skipped) return;
490 ASSERT_TRUE(openTuner());
491
492 bool forced;
493 Result halIsResult;
494 auto isCb = [&](Result result, bool isForced) {
495 halIsResult = result;
496 forced = isForced;
497 };
498
499 // set analog mode
500 auto setResult = mTuner->setAnalogForced(true);
501 ASSERT_TRUE(setResult.isOk());
502 if (Result::INVALID_STATE == setResult) {
503 // if setter fails, getter should fail too - it means the switch is not supported at all
504 auto isResult = mTuner->isAnalogForced(isCb);
505 ASSERT_TRUE(isResult.isOk());
506 EXPECT_EQ(Result::INVALID_STATE, halIsResult);
507 return;
508 }
509 ASSERT_EQ(Result::OK, setResult);
510
511 // check, if it's analog
512 auto isResult = mTuner->isAnalogForced(isCb);
513 ASSERT_TRUE(isResult.isOk());
514 EXPECT_EQ(Result::OK, halIsResult);
515 ASSERT_TRUE(forced);
516
517 // set digital mode
518 setResult = mTuner->setAnalogForced(false);
519 ASSERT_EQ(Result::OK, setResult);
520
521 // check, if it's digital
522 isResult = mTuner->isAnalogForced(isCb);
523 ASSERT_TRUE(isResult.isOk());
524 EXPECT_EQ(Result::OK, halIsResult);
525 ASSERT_FALSE(forced);
526}
527
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700528INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
529 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
530
531} // namespace vts
532} // namespace V1_1
533} // namespace broadcastradio
534} // namespace hardware
535} // namespace android
536
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800537int main(int argc, char** argv) {
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800538 ::testing::InitGoogleTest(&argc, argv);
539 int status = RUN_ALL_TESTS();
540 ALOGI("Test result = %d", status);
541 return status;
542}