Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a70f10b0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "GNSS Service handling System death"

parents 6d7c46ad 917640b7
Loading
Loading
Loading
Loading
+58 −1
Original line number Diff line number Diff line
@@ -46,7 +46,11 @@ GpsCallbacks Gnss::sGnssCb = {
    .gnss_sv_status_cb = gnssSvStatusCb,
};

Gnss::Gnss(gps_device_t* gnssDevice) {
uint32_t Gnss::sCapabilitiesCached = 0;
uint16_t Gnss::sYearOfHwCached = 0;

Gnss::Gnss(gps_device_t* gnssDevice) :
        mDeathRecipient(new GnssHidlDeathRecipient(this)) {
    /* Error out if an instance of the interface already exists. */
    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
    sInterfaceExists = true;
@@ -271,6 +275,9 @@ void Gnss::setCapabilitiesCb(uint32_t capabilities) {
    if (!ret.isOk()) {
        ALOGE("%s: Unable to invoke callback", __func__);
    }

    // Save for reconnection when some legacy hal's don't resend this info
    sCapabilitiesCached = capabilities;
}

void Gnss::acquireWakelockCb() {
@@ -373,6 +380,9 @@ void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
    if (!ret.isOk()) {
            ALOGE("%s: Unable to invoke callback", __func__);
    }

    // Save for reconnection when some legacy hal's don't resend this info
    sYearOfHwCached = info->year_of_hw;
}


@@ -383,7 +393,30 @@ Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback) {
        return false;
    }

    if (callback == nullptr)  {
        ALOGE("%s: Null callback ignored", __func__);
        return false;
    }

    if (sGnssCbIface != NULL) {
        ALOGW("%s called more than once. Unexpected unless test.", __func__);
        sGnssCbIface->unlinkToDeath(mDeathRecipient);
    }

    sGnssCbIface = callback;
    callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);

    // If this was received in the past, send it up again to refresh caller.
    // mGnssIface will override after init() is called below, if needed
    // (though it's unlikely the gps.h capabilities or system info will change.)
    if (sCapabilitiesCached != 0) {
        setCapabilitiesCb(sCapabilitiesCached);
    }
    if (sYearOfHwCached != 0) {
        LegacyGnssSystemInfo info;
        info.year_of_hw = sYearOfHwCached;
        setSystemInfoCb(&info);
    }

    return (mGnssIface->init(&sGnssCb) == 0);
}
@@ -676,6 +709,30 @@ Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching() {
    return mGnssBatching;
}

void Gnss::handleHidlDeath() {
    ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");

    // commands down to the HAL implementation
    stop(); // stop ongoing GPS tracking
    if (mGnssMeasurement != nullptr) {
        mGnssMeasurement->close();
    }
    if (mGnssNavigationMessage != nullptr) {
        mGnssNavigationMessage->close();
    }
    if (mGnssBatching != nullptr) {
        mGnssBatching->stop();
        mGnssBatching->cleanup();
    }
    cleanup();

    /*
     * This has died, so close it off in case (race condition) callbacks happen
     * before HAL processes above messages.
     */
    sGnssCbIface = nullptr;
}

IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
    hw_module_t* module;
    IGnss* iface = nullptr;
+30 −1
Original line number Diff line number Diff line
@@ -52,7 +52,8 @@ using LegacyGnssSystemInfo = ::GnssSystemInfo;
 * Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
 * IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
 */
struct Gnss : public IGnss {
class Gnss : public IGnss {
  public:
    Gnss(gps_device_t* gnss_device);
    ~Gnss();

@@ -122,6 +123,22 @@ struct Gnss : public IGnss {
    static GpsCallbacks sGnssCb;

 private:
    /*
     * For handling system-server death while GNSS service lives on.
     */
    class GnssHidlDeathRecipient : public hidl_death_recipient {
      public:
        GnssHidlDeathRecipient(const sp<Gnss> gnss) : mGnss(gnss) {
        }

        virtual void serviceDied(uint64_t /*cookie*/,
                const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
            mGnss->handleHidlDeath();
        }
      private:
        sp<Gnss> mGnss;
    };

    // for wakelock consolidation, see above
    static void acquireWakelockGnss();
    static void releaseWakelockGnss();
@@ -129,6 +146,11 @@ struct Gnss : public IGnss {
    static bool sWakelockHeldGnss;
    static bool sWakelockHeldFused;

    /*
     * Cleanup for death notification
     */
    void handleHidlDeath();

    sp<GnssXtra> mGnssXtraIface = nullptr;
    sp<AGnssRil> mGnssRil = nullptr;
    sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
@@ -139,10 +161,17 @@ struct Gnss : public IGnss {
    sp<GnssDebug> mGnssDebug = nullptr;
    sp<GnssConfiguration> mGnssConfig = nullptr;
    sp<GnssBatching> mGnssBatching = nullptr;

    sp<GnssHidlDeathRecipient> mDeathRecipient;

    const GpsInterface* mGnssIface = nullptr;
    static sp<IGnssCallback> sGnssCbIface;
    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
    static bool sInterfaceExists;

    // Values saved for resend
    static uint32_t sCapabilitiesCached;
    static uint16_t sYearOfHwCached;
};

extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
+69 −27
Original line number Diff line number Diff line
@@ -33,17 +33,16 @@ using android::hardware::gnss::V1_0::IGnss;
using android::hardware::gnss::V1_0::IGnssCallback;
using android::sp;

#define TIMEOUT_SECONDS 5  // for basic commands/responses
#define TIMEOUT_SEC 3  // for basic commands/responses

// The main test class for GNSS HAL.
class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
 public:
  virtual void SetUp() override {
    /* TODO(b/35678469): Setup the init.rc for VTS such that there's a
     * single caller
     * to the GNSS HAL - as part of confirming that the info & capabilities
     * callbacks trigger.
     */
    // Clean between tests
    capabilities_called_count_ = 0;
    location_called_count_ = 0;
    info_called_count_ = 0;

    gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>();
    ASSERT_NE(gnss_hal_, nullptr);
@@ -53,15 +52,35 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {

    auto result = gnss_hal_->setCallback(gnss_cb_);
    if (!result.isOk()) {
      ALOGE("result of failed callback set %s", result.description().c_str());
      ALOGE("result of failed setCallback %s", result.description().c_str());
    }

    ASSERT_TRUE(result.isOk());
    ASSERT_TRUE(result);

    /* TODO(b/35678469): Implement the capabilities & info (year) checks &
     * value store here.
    /*
     * At least one callback should trigger - it may be capabilites, or
     * system info first, so wait again if capabilities not received.
     */
    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
    if (capabilities_called_count_ == 0) {
      EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
    }

    /*
     * Generally should be 1 capabilites callback -
     * or possibly 2 in some recovery cases (default cached & refreshed)
     */
    EXPECT_GE(capabilities_called_count_, 1);
    EXPECT_LE(capabilities_called_count_, 2);

    /*
     * Clear notify/waiting counter, allowing up till the timeout after
     * the last reply for final startup messages to arrive (esp. system
     * info.)
     */
    while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) {
    }
  }

  virtual void TearDown() override {
@@ -93,9 +112,9 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {

  /* Callback class for data & Event. */
  class GnssCallback : public IGnssCallback {
   public:
    GnssHalTest& parent_;

   public:
    GnssCallback(GnssHalTest& parent) : parent_(parent){};

    virtual ~GnssCallback() = default;
@@ -171,16 +190,33 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
 * Sets up the callback, awaits the capabilities, and calls cleanup
 *
 * Since this is just the basic operation of SetUp() and TearDown(),
 * the function definition is intentionally kept empty
 * the function definition is intentionally empty
 */
TEST_F(GnssHalTest, SetCallbackCapabilitiesCleanup) {}

void CheckLocation(GnssLocation& location) {
/*
 * CheckLocation:
 * Helper function to vet Location fields
 */

void CheckLocation(GnssLocation& location, bool checkAccuracies) {
  EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
  EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
  EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED);
  EXPECT_TRUE(location.gnssLocationFlags &
              GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
  // New uncertainties available in O must be provided,
  // at least when paired with modern hardware (2017+)
  if (checkAccuracies) {
    EXPECT_TRUE(location.gnssLocationFlags &
                GnssLocationFlags::HAS_VERTICAL_ACCURACY);
    EXPECT_TRUE(location.gnssLocationFlags &
                GnssLocationFlags::HAS_SPEED_ACCURACY);
    if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
      EXPECT_TRUE(location.gnssLocationFlags &
                  GnssLocationFlags::HAS_BEARING_ACCURACY);
    }
  }
  EXPECT_GE(location.latitudeDegrees, -90.0);
  EXPECT_LE(location.latitudeDegrees, 90.0);
  EXPECT_GE(location.longitudeDegrees, -180.0);
@@ -190,12 +226,17 @@ void CheckLocation(GnssLocation& location) {
  EXPECT_GE(location.speedMetersPerSec, 0.0);
  EXPECT_LE(location.speedMetersPerSec, 5.0);  // VTS tests are stationary.

  // Non-zero speeds must be reported with an associated bearing
  if (location.speedMetersPerSec > 0.0) {
    EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING);
  }

  /*
   * Tolerating some especially high values for accuracy estimate, in case of
   * first fix with especially poor geoemtry (happens occasionally)
   * first fix with especially poor geometry (happens occasionally)
   */
  EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
  EXPECT_LE(location.horizontalAccuracyMeters, 200.0);
  EXPECT_LE(location.horizontalAccuracyMeters, 250.0);

  /*
   * Some devices may define bearing as -180 to +180, others as 0 to 360.
@@ -220,11 +261,6 @@ void CheckLocation(GnssLocation& location) {

  // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
  EXPECT_GT(location.timestamp, 1.48e12);

  /* TODO(b/35678469): Check if the hardware year is 2017+, and if so,
   * that bearing, plus vertical, speed & bearing accuracy are present.
   * And allow bearing to be not present, only if associated with a speed of 0.0
   */
}

/*
@@ -241,6 +277,9 @@ TEST_F(GnssHalTest, GetLocation) {
#define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3
#define LOCATIONS_TO_CHECK 5

  bool checkMoreAccuracies =
      (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);

  auto result = gnss_hal_->setPositionMode(
      IGnss::GnssPositionMode::MS_BASED,
      IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, MIN_INTERVAL_MSEC,
@@ -254,15 +293,18 @@ TEST_F(GnssHalTest, GetLocation) {
  ASSERT_TRUE(result.isOk());
  ASSERT_TRUE(result);

  EXPECT_EQ(std::cv_status::no_timeout, wait(LOCATION_TIMEOUT_FIRST_SEC));
  EXPECT_EQ(location_called_count_, 1);
  CheckLocation(last_location_);
  // GPS signals initially optional for this test, so don't expect no timeout
  // yet
  wait(LOCATION_TIMEOUT_FIRST_SEC);
  if (location_called_count_ > 0) {
    CheckLocation(last_location_, checkMoreAccuracies);
  }

  for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
    EXPECT_EQ(std::cv_status::no_timeout,
              wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC));
    EXPECT_EQ(location_called_count_, i + 1);
    CheckLocation(last_location_);
    wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC);
    if (location_called_count_ > 0) {
      CheckLocation(last_location_, checkMoreAccuracies);
    }
  }

  result = gnss_hal_->stop();