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

Commit 50e3327c authored by Wyatt Riley's avatar Wyatt Riley
Browse files

GNSS Satellite Use Blacklist HAL

Adding .hal change IGnssConfiguration to enable
external (system) control of satellite usage.
Adding VTS tests of the new .hal (ready for
partners to integrate against.)

Bug: 38269641
Test: .hal & vts builds,
 vts test runs and fails fast (no 1.1 HAL on
 initial test device),
 vts test logs run as expected on a 1.0 device (with tests to make
 this run),
 on-device sanity check of GPS works,
 builds with JNI test code (to be submitted separately)
Change-Id: I72b5045eb0eea30d51ed5098248482cbbfc5aaff
parent c29a0ebf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ hidl_interface {
    srcs: [
        "IGnss.hal",
        "IGnssCallback.hal",
        "IGnssConfiguration.hal",
        "IGnssMeasurement.hal",
    ],
    interfaces: [
+9 −1
Original line number Diff line number Diff line
@@ -18,8 +18,9 @@ package android.hardware.gnss@1.1;

import @1.0::IGnss;

import IGnssMeasurement;
import IGnssCallback;
import IGnssConfiguration;
import IGnssMeasurement;

/** Represents the standard GNSS (Global Navigation Satellite System) interface. */
interface IGnss extends @1.0::IGnss {
@@ -64,6 +65,13 @@ interface IGnss extends @1.0::IGnss {
                        bool lowPowerMode)
             generates (bool success);

   /**
    * This method returns the IGnssConfiguration interface.
    *
    * @return gnssConfigurationIface Handle to the IGnssConfiguration interface.
    */
    getExtensionGnssConfiguration_1_1() generates (IGnssConfiguration gnssConfigurationIface);

   /**
    * This method returns the IGnssMeasurement interface.
    *
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware.gnss@1.1;

import @1.0::IGnssConfiguration;
import @1.0::GnssConstellationType;

/**
 * Extended interface for GNSS Configuration support.
 */
interface IGnssConfiguration extends @1.0::IGnssConfiguration {
    struct BlacklistedSource {
        /**
         * Defines the constellation of the given satellite(s).
         */
        GnssConstellationType constellation;

        /**
         * Satellite (space vehicle) ID number, as defined in GnssSvInfo::svid
         *
         * Or 0 to blacklist all svid's for the specified constellation
         */
        int16_t svid;
    };

    /**
     * Injects a vector of BlacklistedSource(s) which the HAL must not use to calculate the
     * GNSS location output.
     *
     * The superset of all satellite sources provided, including wildcards, in the latest call
     * to this method, is the set of satellites sources that must not be used in calculating
     * location.
     *
     * All measurements from the specified satellites, across frequency bands, are blacklisted
     * together.
     *
     * If this method is never called after the IGnssConfiguration.hal connection is made on boot,
     * or is called with an empty vector, then no satellites are to be blacklisted as a result of
     * this API.
     *
     * This blacklist must be considered as an additional source of which satellites
     * should not be trusted for location on top of existing sources of similar information
     * such as satellite broadcast health being unhealthy and measurement outlier removal.
     *
     * @param blacklist The BlacklistedSource(s) of satellites the HAL must not use.
     *
     * @return success Whether the HAL accepts and abides by the provided blacklist.
     */
    setBlacklist(vec<BlacklistedSource> blacklist) generates (bool success);
};
 No newline at end of file
+148 −5
Original line number Diff line number Diff line
@@ -14,9 +14,6 @@
 * limitations under the License.
 */

#define LOG_TAG "VtsHalGnssV1_1TargetTest"
#include <log/log.h>

#include <gnss_hal_test.h>

#include <chrono>
@@ -31,6 +28,7 @@ GnssHalTest::GnssHalTest()

void GnssHalTest::SetUp() {
    gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>();
    list_gnss_sv_status_.clear();
    ASSERT_NE(gnss_hal_, nullptr);
}

@@ -43,18 +41,156 @@ void GnssHalTest::TearDown() {
    }
}

void GnssHalTest::StopAndClearLocations() {
    auto result = gnss_hal_->stop();

    EXPECT_TRUE(result.isOk());
    EXPECT_TRUE(result);

    /*
     * 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) {
    }
}

void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
    const int kPreferredAccuracy = 0;  // Ideally perfect (matches GnssLocationProvider)
    const int kPreferredTimeMsec = 0;  // Ideally immediate

    auto result = gnss_hal_->setPositionMode_1_1(
        IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
        min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);

    ASSERT_TRUE(result.isOk());
    EXPECT_TRUE(result);
}

bool GnssHalTest::StartAndGetSingleLocation() {
    auto result = gnss_hal_->start();

    EXPECT_TRUE(result.isOk());
    EXPECT_TRUE(result);

    /*
     * GPS signals initially optional for this test, so don't expect fast fix,
     * or no timeout, unless signal is present
     */
    const int kFirstGnssLocationTimeoutSeconds = 15;

    wait(kFirstGnssLocationTimeoutSeconds);
    EXPECT_EQ(location_called_count_, 1);

    if (location_called_count_ > 0) {
        // don't require speed on first fix
        CheckLocation(last_location_, false);
        return true;
    }
    return false;
}

void GnssHalTest::CheckLocation(GnssLocation& location, bool check_speed) {
    bool check_more_accuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);

    EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
    EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
    if (check_speed) {
        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 (check_more_accuracies) {
        EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY);
        if (check_speed) {
            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);
    EXPECT_LE(location.longitudeDegrees, 180.0);
    EXPECT_GE(location.altitudeMeters, -1000.0);
    EXPECT_LE(location.altitudeMeters, 30000.0);
    if (check_speed) {
        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 geometry (happens occasionally)
     */
    EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
    EXPECT_LE(location.horizontalAccuracyMeters, 250.0);

    /*
     * Some devices may define bearing as -180 to +180, others as 0 to 360.
     * Both are okay & understandable.
     */
    if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
        EXPECT_GE(location.bearingDegrees, -180.0);
        EXPECT_LE(location.bearingDegrees, 360.0);
    }
    if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
        EXPECT_GT(location.verticalAccuracyMeters, 0.0);
        EXPECT_LE(location.verticalAccuracyMeters, 500.0);
    }
    if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
        EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
        EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
    }
    if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
        EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
        EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
    }

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

void GnssHalTest::StartAndCheckLocations(int count) {
    const int kMinIntervalMsec = 500;
    const int kLocationTimeoutSubsequentSec = 2;
    const bool kLowPowerMode = true;

    SetPositionMode(kMinIntervalMsec, kLowPowerMode);

    EXPECT_TRUE(StartAndGetSingleLocation());

    for (int i = 1; i < count; i++) {
        EXPECT_EQ(std::cv_status::no_timeout, wait(kLocationTimeoutSubsequentSec));
        EXPECT_EQ(location_called_count_, i + 1);
        // Don't cause confusion by checking details if no location yet
        if (location_called_count_ > 0) {
            // Should be more than 1 location by now, but if not, still don't check first fix speed
            CheckLocation(last_location_, location_called_count_ > 1);
        }
    }
}

void GnssHalTest::notify() {
    std::unique_lock<std::mutex> lock(mtx_);
    notify_count_++;
    cv_.notify_one();
}

std::cv_status GnssHalTest::wait(int timeoutSeconds) {
std::cv_status GnssHalTest::wait(int timeout_seconds) {
    std::unique_lock<std::mutex> lock(mtx_);

    auto status = std::cv_status::no_timeout;
    while (notify_count_ == 0) {
        status = cv_.wait_for(lock, std::chrono::seconds(timeoutSeconds));
        status = cv_.wait_for(lock, std::chrono::seconds(timeout_seconds));
        if (status == std::cv_status::timeout) return status;
    }
    notify_count_--;
@@ -93,3 +229,10 @@ Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation& locat
    parent_.notify();
    return Void();
}

Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(
    const IGnssCallback::GnssSvStatus& svStatus) {
    ALOGI("GnssSvStatus received");
    parent_.list_gnss_sv_status_.emplace_back(svStatus);
    return Void();
}
+29 −110
Original line number Diff line number Diff line
@@ -17,11 +17,14 @@
#ifndef GNSS_HAL_TEST_H_
#define GNSS_HAL_TEST_H_

#define LOG_TAG "VtsHalGnssV1_1TargetTest"

#include <android/hardware/gnss/1.1/IGnss.h>

#include <VtsHalHidlTargetTestBase.h>

#include <condition_variable>
#include <list>
#include <mutex>

using android::hardware::Return;
@@ -32,7 +35,9 @@ using android::hardware::gnss::V1_0::GnssLocation;
using android::hardware::gnss::V1_1::IGnss;
using android::hardware::gnss::V1_1::IGnssCallback;
using android::hardware::gnss::V1_0::GnssLocationFlags;

using android::sp;

#define TIMEOUT_SEC 2  // for basic commands/responses

// The main test class for GNSS HAL.
@@ -48,7 +53,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
    void notify();

    /* Test code calls this function to wait for a callback */
    std::cv_status wait(int timeoutSeconds);
    std::cv_status wait(int timeout_seconds);

    /* Callback class for data & Event. */
    class GnssCallback : public IGnssCallback {
@@ -63,9 +68,6 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
        Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue /* status */) override {
            return Void();
        }
        Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& /* svStatus */) override {
            return Void();
        }
        Return<void> gnssNmeaCb(int64_t /* timestamp */,
                                const android::hardware::hidl_string& /* nmea */) override {
            return Void();
@@ -74,10 +76,11 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
        Return<void> gnssReleaseWakelockCb() override { return Void(); }
        Return<void> gnssRequestTimeCb() override { return Void(); }
        // Actual (test) callback handlers
        Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
        Return<void> gnssLocationCb(const GnssLocation& location) override;
        Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
        Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
        Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
        Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
    };

    /*
@@ -86,120 +89,35 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
     *
     * returns  true if a location was successfully generated
     */
    bool StartAndGetSingleLocation(bool checkAccuracies) {
        auto result = gnss_hal_->start();

        EXPECT_TRUE(result.isOk());
        EXPECT_TRUE(result);

        /*
         * GPS signals initially optional for this test, so don't expect fast fix,
         * or no timeout, unless signal is present
         */
        int firstGnssLocationTimeoutSeconds = 15;

        wait(firstGnssLocationTimeoutSeconds);
        EXPECT_EQ(location_called_count_, 1);

        if (location_called_count_ > 0) {
            // don't require speed on first fix
            CheckLocation(last_location_, checkAccuracies, false);
            return true;
        }
        return false;
    }
    bool StartAndGetSingleLocation();

    /*
     * CheckLocation:
     *   Helper function to vet Location fields when calling setPositionMode_1_1()
     */
    void CheckLocation(GnssLocation& location, bool checkAccuracies, bool checkSpeed) {
        EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
        EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
        if (checkSpeed) {
            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);
            if (checkSpeed) {
                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);
        EXPECT_LE(location.longitudeDegrees, 180.0);
        EXPECT_GE(location.altitudeMeters, -1000.0);
        EXPECT_LE(location.altitudeMeters, 30000.0);
        if (checkSpeed) {
            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 geometry (happens occasionally)
     *   Helper function to vet Location fields
     */
        EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
        EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
    void CheckLocation(GnssLocation& location, bool check_speed);

    /*
         * Some devices may define bearing as -180 to +180, others as 0 to 360.
         * Both are okay & understandable.
     * StartAndCheckLocations:
     *   Helper function to collect, and check a number of
     *   normal ~1Hz locations.
     *
     *   Note this leaves the Location request active, to enable Stop call vs. other call
     *   reordering tests.
     */
        if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
            EXPECT_GE(location.bearingDegrees, -180.0);
            EXPECT_LE(location.bearingDegrees, 360.0);
        }
        if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
            EXPECT_GT(location.verticalAccuracyMeters, 0.0);
            EXPECT_LE(location.verticalAccuracyMeters, 500.0);
        }
        if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
            EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
            EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
        }
        if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
            EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
            EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
        }

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

    /*
     * StopAndClearLocations:
     * Helper function to stop locations
     *
     * returns  true if a location was successfully generated
     * Helper function to stop locations, and clear any remaining notifications
     */
    void StopAndClearLocations() {
        auto result = gnss_hal_->stop();

        EXPECT_TRUE(result.isOk());
        EXPECT_TRUE(result);
    void StopAndClearLocations();

    /*
         * Clear notify/waiting counter, allowing up till the timeout after
         * the last reply for final startup messages to arrive (esp. system
         * info.)
     * SetPositionMode:
     * Helper function to set positioning mode and verify output
     */
        while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) {
        }
    }
    void SetPositionMode(const int min_interval_msec, const bool low_power_mode);

    sp<IGnss> gnss_hal_;         // GNSS HAL to call into
    sp<IGnssCallback> gnss_cb_;  // Primary callback interface
@@ -213,6 +131,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
    int capabilities_called_count_;
    int location_called_count_;
    GnssLocation last_location_;
    list<IGnssCallback::GnssSvStatus> list_gnss_sv_status_;

    int name_called_count_;
    android::hardware::hidl_string last_name_;
Loading