Merge "Add background scan routines and callbacks to broadcast radio HAL."
diff --git a/broadcastradio/1.0/default/BroadcastRadio.cpp b/broadcastradio/1.0/default/BroadcastRadio.cpp
index 45ffdb2..72cdc19 100644
--- a/broadcastradio/1.0/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.0/default/BroadcastRadio.cpp
@@ -63,6 +63,7 @@
     if (rc != 0) {
         ALOGE("couldn't load radio module %s.%s (%s)",
               RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc));
+        mStatus = Result::INVALID_ARGUMENTS;
         return;
     }
     rc = radio_hw_device_open(mod, &mHwDevice);
diff --git a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
index 4ec19c7..ebeadb1 100644
--- a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
+++ b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
@@ -48,21 +48,42 @@
 using ::android::hardware::broadcastradio::V1_0::MetaData;
 
 
+#define RETURN_IF_SKIPPED \
+    if (skipped) { \
+        std::cout << "[  SKIPPED ] This device class is not supported. " << std::endl; \
+        return; \
+    }
+
 // The main test class for Broadcast Radio HIDL HAL.
 
-class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase,
+        public ::testing::WithParamInterface<Class> {
  protected:
     virtual void SetUp() override {
+        ASSERT_EQ(nullptr, mRadio.get());
+
+        radioClass = GetParam();
+        skipped = false;
+
         sp<IBroadcastRadioFactory> factory =
               ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
-        if (factory != 0) {
-            factory->connectModule(Class::AM_FM,
-                             [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
-                if (retval == Result::OK) {
-                  mRadio = result;
-                }
-            });
+        ASSERT_NE(nullptr, factory.get());
+
+        Result connectResult;
+        factory->connectModule(radioClass, [&](Result ret, const sp<IBroadcastRadio>& radio) {
+            connectResult = ret;
+            mRadio = radio;
+            onCallback_l();
+        });
+        EXPECT_EQ(true, waitForCallback(kConnectCallbacktimeoutNs));
+        mCallbackCalled = false;
+
+        if (connectResult == Result::INVALID_ARGUMENTS) {
+            skipped = true;
+            return;
         }
+        ASSERT_EQ(connectResult, Result::OK);
+
         mTunerCallback = new MyCallback(this);
         ASSERT_NE(nullptr, mRadio.get());
         ASSERT_NE(nullptr, mTunerCallback.get());
@@ -175,9 +196,9 @@
     }
 
 
-        BroadcastRadioHidlTest() :
-            mCallbackCalled(false), mBoolCallbackData(false),
-            mResultCallbackData(Result::OK), mHwFailure(false) {}
+    BroadcastRadioHidlTest()
+        : mCallbackCalled(false), mBoolCallbackData(false), mResultCallbackData(Result::OK),
+        mHwFailure(false) {}
 
     void onCallback_l() {
         if (!mCallbackCalled) {
@@ -208,9 +229,12 @@
     bool openTuner();
     bool checkAntenna();
 
+    static const nsecs_t kConnectCallbacktimeoutNs = seconds_to_nanoseconds(1);
     static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
     static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
 
+    Class radioClass;
+    bool skipped;
     sp<IBroadcastRadio> mRadio;
     Properties mHalProperties;
     sp<ITuner> mTuner;
@@ -225,13 +249,6 @@
     bool mHwFailure;
 };
 
-// A class for test environment setup (kept since this file is a template).
-class BroadcastRadioHidlEnvironment : public ::testing::Environment {
- public:
-    virtual void SetUp() {}
-    virtual void TearDown() {}
-};
-
 namespace android {
 namespace hardware {
 namespace broadcastradio {
@@ -331,7 +348,8 @@
  *  - the implementation supports at least one tuner
  *  - the implementation supports at one band
  */
-TEST_F(BroadcastRadioHidlTest, GetProperties) {
+TEST_P(BroadcastRadioHidlTest, GetProperties) {
+    RETURN_IF_SKIPPED;
     EXPECT_EQ(true, getProperties());
 }
 
@@ -342,7 +360,8 @@
  *  - the HAL implements the method
  *  - the method returns 0 (no error) and a valid ITuner interface
  */
-TEST_F(BroadcastRadioHidlTest, OpenTuner) {
+TEST_P(BroadcastRadioHidlTest, OpenTuner) {
+    RETURN_IF_SKIPPED;
     EXPECT_EQ(true, openTuner());
 }
 
@@ -353,7 +372,8 @@
  *  - ITuner destruction gets propagated through HAL
  *  - the openTuner method works well when called for the second time
  */
-TEST_F(BroadcastRadioHidlTest, ReopenTuner) {
+TEST_P(BroadcastRadioHidlTest, ReopenTuner) {
+    RETURN_IF_SKIPPED;
     EXPECT_TRUE(openTuner());
     mTuner.clear();
     EXPECT_TRUE(openTuner());
@@ -366,7 +386,8 @@
  *  - the openTuner method fails when called for the second time without deleting previous
  *    ITuner instance
  */
-TEST_F(BroadcastRadioHidlTest, OpenTunerTwice) {
+TEST_P(BroadcastRadioHidlTest, OpenTunerTwice) {
+    RETURN_IF_SKIPPED;
     EXPECT_TRUE(openTuner());
 
     Result halResult = Result::NOT_INITIALIZED;
@@ -389,7 +410,8 @@
  *  - the configuration callback is received within kConfigCallbacktimeoutNs ns
  *  - the configuration read back from HAl has the same class Id
  */
-TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
+TEST_P(BroadcastRadioHidlTest, SetAndGetConfiguration) {
+    RETURN_IF_SKIPPED;
     ASSERT_EQ(true, openTuner());
     // test setConfiguration
     mCallbackCalled = false;
@@ -422,7 +444,8 @@
  *  - the methods returns INVALID_ARGUMENTS on invalid arguments
  *  - the method recovers and succeeds after passing correct arguments
  */
-TEST_F(BroadcastRadioHidlTest, SetConfigurationFails) {
+TEST_P(BroadcastRadioHidlTest, SetConfigurationFails) {
+    RETURN_IF_SKIPPED;
     ASSERT_EQ(true, openTuner());
 
     // Let's define a config that's bad for sure.
@@ -456,7 +479,8 @@
  *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
  *  - skipping sub-channel or not does not fail the call
  */
-TEST_F(BroadcastRadioHidlTest, Scan) {
+TEST_P(BroadcastRadioHidlTest, Scan) {
+    RETURN_IF_SKIPPED;
     ASSERT_EQ(true, openTuner());
     ASSERT_TRUE(checkAntenna());
     // test scan UP
@@ -483,7 +507,8 @@
  *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
  *  - skipping sub-channel or not does not fail the call
  */
-TEST_F(BroadcastRadioHidlTest, Step) {
+TEST_P(BroadcastRadioHidlTest, Step) {
+    RETURN_IF_SKIPPED;
     ASSERT_EQ(true, openTuner());
     ASSERT_TRUE(checkAntenna());
     // test step UP
@@ -509,7 +534,8 @@
  *  - the methods return 0 (no error)
  *  - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
  */
-TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
+TEST_P(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
+    RETURN_IF_SKIPPED;
     ASSERT_EQ(true, openTuner());
     ASSERT_TRUE(checkAntenna());
 
@@ -566,7 +592,8 @@
  *  - the method returns INVALID_ARGUMENTS when applicable
  *  - the method recovers and succeeds after passing correct arguments
  */
-TEST_F(BroadcastRadioHidlTest, TuneFailsOutOfBounds) {
+TEST_P(BroadcastRadioHidlTest, TuneFailsOutOfBounds) {
+    RETURN_IF_SKIPPED;
     ASSERT_TRUE(openTuner());
     ASSERT_TRUE(checkAntenna());
 
@@ -595,9 +622,12 @@
     EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
 }
 
+INSTANTIATE_TEST_CASE_P(
+    BroadcastRadioHidlTestCases,
+    BroadcastRadioHidlTest,
+    ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
 
 int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
   ::testing::InitGoogleTest(&argc, argv);
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
diff --git a/configstore/utils/include/configstore/Utils.h b/configstore/utils/include/configstore/Utils.h
index 98ccae9..46cc9b0 100644
--- a/configstore/utils/include/configstore/Utils.h
+++ b/configstore/utils/include/configstore/Utils.h
@@ -20,6 +20,10 @@
 #include <hidl/Status.h>
 #include <stdatomic.h>
 
+#pragma push_macro("LOG_TAG")
+#undef LOG_TAG
+#define LOG_TAG "ConfigStoreUtil"
+
 namespace android {
 namespace hardware {
 namespace configstore {
@@ -39,9 +43,13 @@
             // fallback to the default value
             ret.specified = false;
         } else {
-            (*configs.*func)([&ret](V v) {
+            auto status = (*configs.*func)([&ret](V v) {
                 ret = v;
             });
+            if (!status.isOk()) {
+                ALOGE("HIDL call failed. %s", status.description().c_str());
+                ret.specified = false;
+            }
         }
 
         return ret;
@@ -91,4 +99,6 @@
 }  // namespace hardware
 }  // namespace android
 
+#pragma pop_macro("LOG_TAG")
+
 #endif  // ANDROID_HARDWARE_CONFIGSTORE_UTILS_H
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index 21b7136..bd5cc2e 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -31,10 +31,16 @@
 using android::hardware::gnss::V1_0::GnssLocationFlags;
 using android::hardware::gnss::V1_0::IGnss;
 using android::hardware::gnss::V1_0::IGnssCallback;
+using android::hardware::gnss::V1_0::IGnssDebug;
+using android::hardware::gnss::V1_0::IGnssMeasurement;
 using android::sp;
 
 #define TIMEOUT_SEC 3  // for basic commands/responses
 
+// Set these false for release, true for stronger test
+#define GNSS_SIGNAL_IS_PRESENT false
+#define GNSS_ASSISTANCE_IS_PRESENT false
+
 // The main test class for GNSS HAL.
 class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
  public:
@@ -273,7 +279,12 @@
 #define PREFERRED_ACCURACY 0   // Ideally perfect (matches GnssLocationProvider)
 #define PREFERRED_TIME_MSEC 0  // Ideally immediate
 
+#if GNSS_ASSISTANCE_IS_PRESENT
+#define LOCATION_TIMEOUT_FIRST_SEC 15
+#else
 #define LOCATION_TIMEOUT_FIRST_SEC 45
+#endif
+
 #define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3
 #define LOCATIONS_TO_CHECK 5
 
@@ -286,16 +297,21 @@
       PREFERRED_ACCURACY, PREFERRED_TIME_MSEC);
 
   ASSERT_TRUE(result.isOk());
-  ASSERT_TRUE(result);
+  EXPECT_TRUE(result);
 
   result = gnss_hal_->start();
 
   ASSERT_TRUE(result.isOk());
-  ASSERT_TRUE(result);
+  EXPECT_TRUE(result);
 
-  // GPS signals initially optional for this test, so don't expect no timeout
-  // yet
+  /*
+   * GPS signals initially optional for this test, so don't expect no timeout
+   * yet
+   */
   wait(LOCATION_TIMEOUT_FIRST_SEC);
+  if (GNSS_SIGNAL_IS_PRESENT) {
+    ASSERT_GT(location_called_count_, 0);
+  }
   if (location_called_count_ > 0) {
     CheckLocation(last_location_, checkMoreAccuracies);
   }
@@ -313,6 +329,88 @@
   ASSERT_TRUE(result);
 }
 
+/*
+ * InjectDelete:
+ * Ensures that calls to inject and/or delete information state are handled.
+ * Better tests await GPS signal
+ */
+TEST_F(GnssHalTest, InjectDelete) {
+  // confidently, well north of Alaska
+  auto result = gnss_hal_->injectLocation(80.0, -170.0, 1000.0);
+
+  // TODO: full self-diff including TODO's :)
+  ASSERT_TRUE(result.isOk());
+  EXPECT_TRUE(result);
+
+  // fake time, but generally reasonable values (time in Aug. 2018)
+  result = gnss_hal_->injectTime(1534567890123L, 123456L, 10000L);
+
+  ASSERT_TRUE(result.isOk());
+  EXPECT_TRUE(result);
+
+  auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_ALL);
+
+  ASSERT_TRUE(resultVoid.isOk());
+}
+
+/*
+ * GetAllExtentions:
+ * Tries getting all optional extensions, and ensures a valid return
+ *   null or actual extension, no crash.
+ * Confirms year-based required extensions (Measurement & Debug) are present
+ */
+TEST_F(GnssHalTest, GetAllExtensions) {
+  // Basic call-is-handled checks
+  auto gnssXtra = gnss_hal_->getExtensionXtra();
+  ASSERT_TRUE(gnssXtra.isOk());
+
+  auto gnssRil = gnss_hal_->getExtensionAGnssRil();
+  ASSERT_TRUE(gnssRil.isOk());
+
+  auto gnssAgnss = gnss_hal_->getExtensionAGnss();
+  ASSERT_TRUE(gnssAgnss.isOk());
+
+  auto gnssNi = gnss_hal_->getExtensionGnssNi();
+  ASSERT_TRUE(gnssNi.isOk());
+
+  auto gnssNavigationMessage = gnss_hal_->getExtensionGnssNavigationMessage();
+  ASSERT_TRUE(gnssNavigationMessage.isOk());
+
+  auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration();
+  ASSERT_TRUE(gnssConfiguration.isOk());
+
+  auto gnssGeofencing = gnss_hal_->getExtensionGnssGeofencing();
+  ASSERT_TRUE(gnssGeofencing.isOk());
+
+  auto gnssBatching = gnss_hal_->getExtensionGnssBatching();
+  ASSERT_TRUE(gnssBatching.isOk());
+
+  // Verifying, in some cases, that these return actual extensions
+  auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement();
+  ASSERT_TRUE(gnssMeasurement.isOk());
+  if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) {
+    sp<IGnssMeasurement> iGnssMeas = gnssMeasurement;
+    EXPECT_NE(iGnssMeas, nullptr);
+  }
+
+  auto gnssDebug = gnss_hal_->getExtensionGnssDebug();
+  ASSERT_TRUE(gnssDebug.isOk());
+  if (info_called_count_ > 0 && last_info_.yearOfHw >= 2017) {
+    sp<IGnssDebug> iGnssDebug = gnssDebug;
+    EXPECT_NE(iGnssDebug, nullptr);
+  }
+}
+
+/*
+ * MeasurementCapabilities:
+ * Verifies that modern hardware supports measurement capabilities.
+ */
+TEST_F(GnssHalTest, MeasurementCapabilites) {
+  if (info_called_count_ > 0 && last_info_.yearOfHw >= 2016) {
+    EXPECT_TRUE(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS);
+  }
+}
+
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
   int status = RUN_ALL_TESTS();