Home | History | Annotate | Download | only in functional
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "BroadcastRadioHidlHalTest"
     18 #include <VtsHalHidlTargetTestBase.h>
     19 #include <android-base/logging.h>
     20 #include <cutils/native_handle.h>
     21 #include <cutils/properties.h>
     22 #include <hidl/HidlTransportSupport.h>
     23 #include <utils/threads.h>
     24 
     25 #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
     26 #include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
     27 #include <android/hardware/broadcastradio/1.1/ITuner.h>
     28 #include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
     29 #include <android/hardware/broadcastradio/1.1/types.h>
     30 
     31 
     32 namespace V1_0 = ::android::hardware::broadcastradio::V1_0;
     33 
     34 using ::android::sp;
     35 using ::android::Mutex;
     36 using ::android::Condition;
     37 using ::android::hardware::Return;
     38 using ::android::hardware::Void;
     39 using ::android::hardware::broadcastradio::V1_0::BandConfig;
     40 using ::android::hardware::broadcastradio::V1_0::Class;
     41 using ::android::hardware::broadcastradio::V1_0::Direction;
     42 using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
     43 using ::android::hardware::broadcastradio::V1_0::MetaData;
     44 using ::android::hardware::broadcastradio::V1_0::Properties;
     45 using ::android::hardware::broadcastradio::V1_1::IBroadcastRadioFactory;
     46 using ::android::hardware::broadcastradio::V1_1::ITuner;
     47 using ::android::hardware::broadcastradio::V1_1::ITunerCallback;
     48 using ::android::hardware::broadcastradio::V1_1::ProgramInfo;
     49 using ::android::hardware::broadcastradio::V1_1::Result;
     50 using ::android::hardware::broadcastradio::V1_1::ProgramListResult;
     51 
     52 
     53 // The main test class for Broadcast Radio HIDL HAL.
     54 
     55 class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase {
     56  protected:
     57     virtual void SetUp() override {
     58         auto factory = ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
     59         if (factory != 0) {
     60             factory->connectModule(Class::AM_FM,
     61                              [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
     62                 if (retval == Result::OK) {
     63                   mRadio = IBroadcastRadio::castFrom(result);
     64                 }
     65             });
     66         }
     67         mTunerCallback = new MyCallback(this);
     68         ASSERT_NE(nullptr, mRadio.get());
     69         ASSERT_NE(nullptr, mTunerCallback.get());
     70     }
     71 
     72     virtual void TearDown() override {
     73         mTuner.clear();
     74         mRadio.clear();
     75     }
     76 
     77     class MyCallback : public ITunerCallback {
     78      public:
     79 
     80         // ITunerCallback methods (see doc in ITunerCallback.hal)
     81         virtual Return<void> hardwareFailure() {
     82             ALOGI("%s", __FUNCTION__);
     83             mParentTest->onHwFailureCallback();
     84             return Void();
     85         }
     86 
     87         virtual Return<void> configChange(Result result, const BandConfig& config __unused) {
     88             ALOGI("%s result %d", __FUNCTION__, result);
     89             mParentTest->onResultCallback(result);
     90             return Void();
     91         }
     92 
     93         virtual Return<void> tuneComplete(Result result __unused, const V1_0::ProgramInfo& info __unused) {
     94             return Void();
     95         }
     96 
     97         virtual Return<void> tuneComplete_1_1(Result result, const ProgramInfo& info __unused) {
     98             ALOGI("%s result %d", __FUNCTION__, result);
     99             mParentTest->onResultCallback(result);
    100             return Void();
    101         }
    102 
    103         virtual Return<void> afSwitch(const V1_0::ProgramInfo& info __unused) {
    104             return Void();
    105         }
    106 
    107         virtual Return<void> afSwitch_1_1(const ProgramInfo& info __unused) {
    108             return Void();
    109         }
    110 
    111         virtual Return<void> antennaStateChange(bool connected) {
    112             ALOGI("%s connected %d", __FUNCTION__, connected);
    113             return Void();
    114         }
    115 
    116         virtual Return<void> trafficAnnouncement(bool active) {
    117             ALOGI("%s active %d", __FUNCTION__, active);
    118             return Void();
    119         }
    120 
    121         virtual Return<void> emergencyAnnouncement(bool active) {
    122             ALOGI("%s active %d", __FUNCTION__, active);
    123             return Void();
    124         }
    125 
    126         virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
    127                            const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
    128             ALOGI("%s", __FUNCTION__);
    129             return Void();
    130         }
    131 
    132         virtual Return<void> backgroundScanComplete(ProgramListResult result __unused) {
    133             return Void();
    134         }
    135 
    136         virtual Return<void> programListChanged() {
    137             return Void();
    138         }
    139 
    140                 MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
    141 
    142      private:
    143         // BroadcastRadioHidlTest instance to which callbacks will be notified.
    144         BroadcastRadioHidlTest *mParentTest;
    145     };
    146 
    147 
    148     /**
    149      * Method called by MyCallback when a callback with no status or boolean value is received
    150      */
    151     void onCallback() {
    152         Mutex::Autolock _l(mLock);
    153         onCallback_l();
    154     }
    155 
    156     /**
    157      * Method called by MyCallback when hardwareFailure() callback is received
    158      */
    159     void onHwFailureCallback() {
    160         Mutex::Autolock _l(mLock);
    161         mHwFailure = true;
    162         onCallback_l();
    163     }
    164 
    165     /**
    166      * Method called by MyCallback when a callback with status is received
    167      */
    168     void onResultCallback(Result result) {
    169         Mutex::Autolock _l(mLock);
    170         mResultCallbackData = result;
    171         onCallback_l();
    172     }
    173 
    174     /**
    175      * Method called by MyCallback when a boolean indication is received
    176      */
    177     void onBoolCallback(bool result) {
    178         Mutex::Autolock _l(mLock);
    179         mBoolCallbackData = result;
    180         onCallback_l();
    181     }
    182 
    183 
    184         BroadcastRadioHidlTest() :
    185             mCallbackCalled(false), mBoolCallbackData(false),
    186             mResultCallbackData(Result::OK), mHwFailure(false) {}
    187 
    188     void onCallback_l() {
    189         if (!mCallbackCalled) {
    190             mCallbackCalled = true;
    191             mCallbackCond.broadcast();
    192         }
    193     }
    194 
    195 
    196     bool waitForCallback(nsecs_t reltime = 0) {
    197         Mutex::Autolock _l(mLock);
    198         nsecs_t endTime = systemTime() + reltime;
    199         while (!mCallbackCalled) {
    200             if (reltime == 0) {
    201                 mCallbackCond.wait(mLock);
    202             } else {
    203                 nsecs_t now = systemTime();
    204                 if (now > endTime) {
    205                     return false;
    206                 }
    207                 mCallbackCond.waitRelative(mLock, endTime - now);
    208             }
    209         }
    210         return true;
    211     }
    212 
    213     bool getProperties();
    214     bool openTuner();
    215     bool checkAntenna();
    216 
    217     static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
    218     static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
    219 
    220     sp<IBroadcastRadio> mRadio;
    221     Properties mHalProperties;
    222     sp<ITuner> mTuner;
    223     sp<MyCallback> mTunerCallback;
    224     Mutex mLock;
    225     Condition mCallbackCond;
    226     bool mCallbackCalled;
    227     bool mBoolCallbackData;
    228     Result mResultCallbackData;
    229     bool mHwFailure;
    230 };
    231 
    232 // A class for test environment setup (kept since this file is a template).
    233 class BroadcastRadioHidlEnvironment : public ::testing::Environment {
    234  public:
    235     virtual void SetUp() {}
    236     virtual void TearDown() {}
    237 };
    238 
    239 bool BroadcastRadioHidlTest::getProperties()
    240 {
    241     if (mHalProperties.bands.size() == 0) {
    242         Result halResult = Result::NOT_INITIALIZED;
    243         Return<void> hidlReturn =
    244                 mRadio->getProperties([&](Result result, const Properties& properties) {
    245                         halResult = result;
    246                         if (result == Result::OK) {
    247                             mHalProperties = properties;
    248                         }
    249                     });
    250 
    251         EXPECT_TRUE(hidlReturn.isOk());
    252         EXPECT_EQ(Result::OK, halResult);
    253         EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
    254         EXPECT_GT(mHalProperties.numTuners, 0u);
    255         EXPECT_GT(mHalProperties.bands.size(), 0u);
    256     }
    257     return mHalProperties.bands.size() > 0;
    258 }
    259 
    260 bool BroadcastRadioHidlTest::openTuner()
    261 {
    262     if (!getProperties()) {
    263         return false;
    264     }
    265     if (mTuner.get() == nullptr) {
    266         Result halResult = Result::NOT_INITIALIZED;
    267         auto hidlReturn = mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
    268                 [&](Result result, const sp<V1_0::ITuner>& tuner) {
    269                     halResult = result;
    270                     if (result == Result::OK) {
    271                         mTuner = ITuner::castFrom(tuner);
    272                     }
    273                 });
    274         EXPECT_TRUE(hidlReturn.isOk());
    275         EXPECT_EQ(Result::OK, halResult);
    276         EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
    277     }
    278     EXPECT_NE(nullptr, mTuner.get());
    279     return nullptr != mTuner.get();
    280 }
    281 
    282 bool BroadcastRadioHidlTest::checkAntenna()
    283 {
    284     BandConfig halConfig;
    285     Result halResult = Result::NOT_INITIALIZED;
    286     Return<void> hidlReturn =
    287             mTuner->getConfiguration([&](Result result, const BandConfig& config) {
    288                 halResult = result;
    289                 if (result == Result::OK) {
    290                     halConfig = config;
    291                 }
    292             });
    293 
    294     return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
    295 }
    296 
    297 
    298 /**
    299  * Test IBroadcastRadio::getProperties() method
    300  *
    301  * Verifies that:
    302  *  - the HAL implements the method
    303  *  - the method returns 0 (no error)
    304  *  - the implementation class is AM_FM
    305  *  - the implementation supports at least one tuner
    306  *  - the implementation supports at one band
    307  */
    308 TEST_F(BroadcastRadioHidlTest, GetProperties) {
    309     EXPECT_TRUE(getProperties());
    310 }
    311 
    312 /**
    313  * Test IBroadcastRadio::openTuner() method
    314  *
    315  * Verifies that:
    316  *  - the HAL implements the method
    317  *  - the method returns 0 (no error) and a valid ITuner interface
    318  */
    319 TEST_F(BroadcastRadioHidlTest, OpenTuner) {
    320     EXPECT_TRUE(openTuner());
    321 }
    322 
    323 /**
    324  * Test ITuner::setConfiguration() and getConfiguration methods
    325  *
    326  * Verifies that:
    327  *  - the HAL implements both methods
    328  *  - the methods return 0 (no error)
    329  *  - the configuration callback is received within kConfigCallbacktimeoutNs ns
    330  *  - the configuration read back from HAl has the same class Id
    331  */
    332 TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
    333     ASSERT_TRUE(openTuner());
    334     // test setConfiguration
    335     mCallbackCalled = false;
    336     Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
    337     EXPECT_TRUE(hidlResult.isOk());
    338     EXPECT_EQ(Result::OK, hidlResult);
    339     EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
    340     EXPECT_EQ(Result::OK, mResultCallbackData);
    341 
    342     // test getConfiguration
    343     BandConfig halConfig;
    344     Result halResult;
    345     Return<void> hidlReturn =
    346             mTuner->getConfiguration([&](Result result, const BandConfig& config) {
    347                 halResult = result;
    348                 if (result == Result::OK) {
    349                     halConfig = config;
    350                 }
    351             });
    352     EXPECT_TRUE(hidlReturn.isOk());
    353     EXPECT_EQ(Result::OK, halResult);
    354     EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
    355 }
    356 
    357 /**
    358  * Test ITuner::scan
    359  *
    360  * Verifies that:
    361  *  - the HAL implements the method
    362  *  - the method returns 0 (no error)
    363  *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
    364  */
    365 TEST_F(BroadcastRadioHidlTest, Scan) {
    366     ASSERT_TRUE(openTuner());
    367     ASSERT_TRUE(checkAntenna());
    368     // test scan UP
    369     mCallbackCalled = false;
    370     Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
    371     EXPECT_TRUE(hidlResult.isOk());
    372     EXPECT_EQ(Result::OK, hidlResult);
    373     EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
    374 
    375     // test scan DOWN
    376     mCallbackCalled = false;
    377     hidlResult = mTuner->scan(Direction::DOWN, true);
    378     EXPECT_TRUE(hidlResult.isOk());
    379     EXPECT_EQ(Result::OK, hidlResult);
    380     EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
    381 }
    382 
    383 /**
    384  * Test ITuner::step
    385  *
    386  * Verifies that:
    387  *  - the HAL implements the method
    388  *  - the method returns 0 (no error)
    389  *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
    390  */
    391 TEST_F(BroadcastRadioHidlTest, Step) {
    392     ASSERT_TRUE(openTuner());
    393     ASSERT_TRUE(checkAntenna());
    394     // test step UP
    395     mCallbackCalled = false;
    396     Return<Result> hidlResult = mTuner->step(Direction::UP, true);
    397     EXPECT_TRUE(hidlResult.isOk());
    398     EXPECT_EQ(Result::OK, hidlResult);
    399     EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
    400 
    401     // test step DOWN
    402     mCallbackCalled = false;
    403     hidlResult = mTuner->step(Direction::DOWN, true);
    404     EXPECT_TRUE(hidlResult.isOk());
    405     EXPECT_EQ(Result::OK, hidlResult);
    406     EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
    407 }
    408 
    409 /**
    410  * Test ITuner::tune,  getProgramInformation and cancel methods
    411  *
    412  * Verifies that:
    413  *  - the HAL implements the methods
    414  *  - the methods return 0 (no error)
    415  *  - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
    416  */
    417 TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
    418     ASSERT_TRUE(openTuner());
    419     ASSERT_TRUE(checkAntenna());
    420 
    421     // test tune
    422     ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
    423     ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
    424 
    425     // test scan UP
    426     uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
    427     uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
    428     uint32_t spacing = mHalProperties.bands[0].spacings[0];
    429 
    430     uint32_t channel =
    431             lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
    432     mCallbackCalled = false;
    433     mResultCallbackData = Result::NOT_INITIALIZED;
    434     Return<Result> hidlResult = mTuner->tune(channel, 0);
    435     EXPECT_TRUE(hidlResult.isOk());
    436     EXPECT_EQ(Result::OK, hidlResult);
    437     EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
    438 
    439     // test getProgramInformation
    440     ProgramInfo halInfo;
    441     Result halResult = Result::NOT_INITIALIZED;
    442     Return<void> hidlReturn = mTuner->getProgramInformation_1_1(
    443         [&](Result result, const ProgramInfo& info) {
    444             halResult = result;
    445             if (result == Result::OK) {
    446                 halInfo = info;
    447             }
    448         });
    449     EXPECT_TRUE(hidlReturn.isOk());
    450     EXPECT_EQ(Result::OK, halResult);
    451     auto &halInfo_1_1 = halInfo.base;
    452     if (mResultCallbackData == Result::OK) {
    453         EXPECT_TRUE(halInfo_1_1.tuned);
    454         EXPECT_LE(halInfo_1_1.channel, upperLimit);
    455         EXPECT_GE(halInfo_1_1.channel, lowerLimit);
    456     } else {
    457         EXPECT_EQ(false, halInfo_1_1.tuned);
    458     }
    459 
    460     // test cancel
    461     mTuner->tune(lowerLimit, 0);
    462     hidlResult = mTuner->cancel();
    463     EXPECT_TRUE(hidlResult.isOk());
    464     EXPECT_EQ(Result::OK, hidlResult);
    465 }
    466 
    467 
    468 int main(int argc, char** argv) {
    469   ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
    470   ::testing::InitGoogleTest(&argc, argv);
    471   int status = RUN_ALL_TESTS();
    472   ALOGI("Test result = %d", status);
    473   return status;
    474 }
    475