diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl new file mode 100644 index 0000000000..89f5d53106 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +parcelable BlocklistedSource { + android.hardware.gnss.GnssConstellationType constellation; + int svid; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl new file mode 100644 index 0000000000..30d0227577 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@Backing(type="int") @VintfStability +enum GnssConstellationType { + UNKNOWN = 0, + GPS = 1, + SBAS = 2, + GLONASS = 3, + QZSS = 4, + BEIDOU = 5, + GALILEO = 6, + IRNSS = 7, +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl index 33377ca906..146577ef90 100644 --- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl @@ -18,5 +18,9 @@ package android.hardware.gnss; @VintfStability interface IGnss { + void setCallback(in android.hardware.gnss.IGnssCallback callback); + void close(); android.hardware.gnss.IGnssPsds getExtensionPsds(); + android.hardware.gnss.IGnssConfiguration getExtensionGnssConfiguration(); + const int ERROR_INVALID_ARGUMENT = 1; } diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl new file mode 100644 index 0000000000..62870d6871 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssCallback { + void gnssSetCapabilitiesCb(in int capabilities); + const int CAPABILITY_SATELLITE_BLOCKLIST = 1; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl new file mode 100644 index 0000000000..5af30cf237 --- /dev/null +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL interface (or parcelable). Do not try to +// edit this file. It looks like you are doing that because you have modified +// an AIDL interface in a backward-incompatible way, e.g., deleting a function +// from an interface or a field from a parcelable and it broke the build. That +// breakage is intended. +// +// You must not make a backward incompatible changes to the AIDL files built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.gnss; +@VintfStability +interface IGnssConfiguration { + void setSuplVersion(in int version); + void setSuplMode(in int mode); + void setLppProfile(in int lppProfile); + void setGlonassPositioningProtocol(in int protocol); + void setEmergencySuplPdn(in boolean enable); + void setEsExtensionSec(in int emergencyExtensionSeconds); + void setBlocklist(in android.hardware.gnss.BlocklistedSource[] blocklist); + const int SUPL_MODE_MSB = 1; + const int SUPL_MODE_MSA = 2; + const int LPP_PROFILE_USER_PLANE = 1; + const int LPP_PROFILE_CONTROL_PLANE = 2; + const int GLONASS_POS_PROTOCOL_RRC_CPLANE = 1; + const int GLONASS_POS_PROTOCOL_RRLP_UPLANE = 2; + const int GLONASS_POS_PROTOCOL_LPP_UPLANE = 4; +} diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl index 352a694f0b..ddef9280ed 100644 --- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl @@ -18,6 +18,6 @@ package android.hardware.gnss; @VintfStability interface IGnssPsds { - boolean injectPsdsData(in android.hardware.gnss.PsdsType psdsType, in byte[] psdsData); - boolean setCallback(in android.hardware.gnss.IGnssPsdsCallback callback); + void injectPsdsData(in android.hardware.gnss.PsdsType psdsType, in byte[] psdsData); + void setCallback(in android.hardware.gnss.IGnssPsdsCallback callback); } diff --git a/gnss/aidl/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/android/hardware/gnss/BlocklistedSource.aidl new file mode 100644 index 0000000000..2fde5b20fd --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/BlocklistedSource.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 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; + +import android.hardware.gnss.GnssConstellationType; + +/** + * Represents a blocklisted source. + */ +@VintfStability +parcelable BlocklistedSource { + /** + * Defines the constellation of the given satellite(s). + */ + GnssConstellationType constellation; + + /** + * Satellite (space vehicle) ID number, as defined in GnssSvInfo::svid, or 0 to blocklist all + * svid's for the specified constellation. + */ + int svid; +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/android/hardware/gnss/GnssConstellationType.aidl new file mode 100644 index 0000000000..af3e089c5e --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/GnssConstellationType.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 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; + +/** + * GNSS constellation type + * + * This is to specify the navigation satellite system, for example, as listed in Section 3.5 in + * RINEX Version 3.04. + */ +@VintfStability +@Backing(type="int") +enum GnssConstellationType { + UNKNOWN = 0, + /** Global Positioning System. */ + GPS = 1, + /** Satellite-Based Augmentation System. */ + SBAS = 2, + /** Global Navigation Satellite System. */ + GLONASS = 3, + /** Quasi-Zenith Satellite System. */ + QZSS = 4, + /** BeiDou Navigation Satellite System. */ + BEIDOU = 5, + /** Galileo Navigation Satellite System. */ + GALILEO = 6, + /** Indian Regional Navigation Satellite System. */ + IRNSS = 7, +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl index 1da254c7ef..24632aa8d6 100644 --- a/gnss/aidl/android/hardware/gnss/IGnss.aidl +++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl @@ -16,7 +16,9 @@ package android.hardware.gnss; +import android.hardware.gnss.IGnssCallback; import android.hardware.gnss.IGnssPsds; +import android.hardware.gnss.IGnssConfiguration; /** * Represents the standard GNSS (Global Navigation Satellite System) interface. @@ -24,10 +26,53 @@ import android.hardware.gnss.IGnssPsds; @VintfStability interface IGnss { + /** + * All GNSS Binder calls may return a ServiceSpecificException with the following error + * codes. + */ + const int ERROR_INVALID_ARGUMENT = 1; + + /** + * Opens the interface and provides the callback routines to the implementation of this + * interface. + * + * The framework calls this method to instruct the GPS engine to prepare for serving requests + * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the + * framework upon successful return from this method until cleanup() method is called to + * close this interface. + * + * @param callback Callback interface for IGnss. + */ + void setCallback(in IGnssCallback callback); + + /** + * Closes the interface. + * + * The close() method is called by the framework to tell the GNSS HAL implementation to + * clear the callback and not expect any GNSS requests in the immediate future - e.g. this may + * be called when location is disabled by a user setting or low battery conditions. The GNSS HAL + * implementation must immediately stop responding to any existing requests until the + * setCallback() method is called again and the requests are re-initiated by the framework. + * + * After this method is called, the GNSS HAL implementation may choose to modify GNSS hardware + * states to save power. It is expected that when setCallback() method is called again to + * reopen this interface, to serve requests, there may be some minor delays in GNSS response + * requests as hardware readiness states are restored, not to exceed those that occur on normal + * device boot up. + */ + void close(); + /** * This method returns the IGnssPsds interface. * * @return Handle to the IGnssPsds interface. */ IGnssPsds getExtensionPsds(); + + /** + * This method returns the IGnssConfiguration interface. + * + * @return Handle to the IGnssConfiguration interface. + */ + IGnssConfiguration getExtensionGnssConfiguration(); } \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl new file mode 100644 index 0000000000..a46a018141 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 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; + +import android.hardware.gnss.IGnssPsds; +import android.hardware.gnss.IGnssConfiguration; + +/** + * This interface is required for the HAL to communicate certain information + * like status and location info back to the framework, the framework implements + * the interfaces and passes a handle to the HAL. + */ +@VintfStability +interface IGnssCallback { + + /** Capability bit mask indicating GNSS supports blocklisting satellites */ + const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 0; + + /** + * Callback to inform framework of the GNSS HAL implementation's capabilities. + * + * @param capabilities Capability parameter is a bit field of the Capability bit masks. + */ + void gnssSetCapabilitiesCb(in int capabilities); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/android/hardware/gnss/IGnssConfiguration.aidl new file mode 100644 index 0000000000..e0ad3575f0 --- /dev/null +++ b/gnss/aidl/android/hardware/gnss/IGnssConfiguration.aidl @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2020 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; + +import android.hardware.gnss.BlocklistedSource; + +/** + * Extended interface for GNSS Configuration support. + */ +@VintfStability +interface IGnssConfiguration { + + /** SUPL mode bitmask for Mobile Station Based. */ + const int SUPL_MODE_MSB = 0x01; + + /** SUPL mode bitmask for Mobile Station Assisted. */ + const int SUPL_MODE_MSA = 0x02; + + /** LPP profile settings bitmask for enabling LTE Positioning Protocol User Plane. */ + const int LPP_PROFILE_USER_PLANE = 0x01; + + /** LPP profile settings bitmask for enabling LTE Positioning Protocol Control Plane. */ + const int LPP_PROFILE_CONTROL_PLANE = 0x02; + + /** A-Glonass positioning protocol bitmask for Radio Resource Control (RRC) Control Plane. */ + const int GLONASS_POS_PROTOCOL_RRC_CPLANE = 0x01; + + /** A-Glonass positioning protocol bitmask for Radio Resource Location User Plane. */ + const int GLONASS_POS_PROTOCOL_RRLP_UPLANE = 0x02; + + /** A-Glonass positioning protocol bitmask for LTE Positioning Protocol User Plane. */ + const int GLONASS_POS_PROTOCOL_LPP_UPLANE = 0x04; + + /** + * This method sets the SUPL version requested by Carrier. The GNSS HAL must use this version + * of the SUPL protocol if supported. + * + * @param version SUPL version requested by carrier. This is a bit mask with bits 0:7 + * representing a service indicator field, bits 8:15 representing the minor version and bits + * 16:23 representing the major version. + */ + void setSuplVersion(in int version); + + /** + * This method sets the SUPL mode. + * + * @param mode Bitmask that specifies the SUPL mode which is set with the SUPL_MODE_* constants. + */ + void setSuplMode(in int mode); + + /** + * This method sets the LTE Positioning Profile configuration. + * + * @param lppProfile Bitmask that specifies the LTE Positioning Profile configuration to be set + * as per the LPP_PROFILE_* constants. If none of the bits are set, the default setting is + * Radio Resource Location Protocol (RRLP). + */ + void setLppProfile(in int lppProfile); + + /** + * This method selects positioning protocol on A-Glonass system. + * + * @param protocol Bitmask that specifies the positioning protocol to be set as per + * GLONASS_POS_PROTOCOL_* constants. + */ + void setGlonassPositioningProtocol(in int protocol); + + /** + * This method configures which PDN to use. + * + * @param enable Use emergency PDN if true and regular PDN if false. + */ + void setEmergencySuplPdn(in boolean enable); + + /** + * This method sets the emergency session extension duration. The GNSS HAL + * implementation must serve emergency SUPL and Control Plane network initiated + * location requests for this extra duration after the user initiated emergency + * session ends. + * + * @param emergencyExtensionSeconds Number of seconds to extend the emergency + * session duration post emergency call. + */ + void setEsExtensionSec(in int emergencyExtensionSeconds); + + /** + * Injects a vector of BlocklistedSource(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 blocklisted + * 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 blocklisted as a result of + * this API. + * + * This blocklist 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 blocklist The BlocklistedSource(s) of satellites the HAL must not use. + */ + void setBlocklist(in BlocklistedSource[] blocklist); +} \ No newline at end of file diff --git a/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl index 6f53d6faac..7c4609653f 100644 --- a/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl +++ b/gnss/aidl/android/hardware/gnss/IGnssPsds.aidl @@ -32,18 +32,14 @@ interface IGnssPsds { * @param psdsType Type of PSDS data. * @param psdsData GNSS PSDS data. Framework must not parse the data since the data format is * opaque to framework. - * - * @return True if the operation is successful. */ - boolean injectPsdsData(in PsdsType psdsType, in byte[] psdsData); + void injectPsdsData(in PsdsType psdsType, in byte[] psdsData); /** * Opens the PSDS interface and provides the callback routines to the implementation of this * interface. * * @param callback Handle to the IGnssPsdsCallback interface. - * - * @return True if the operation is successful. */ - boolean setCallback(in IGnssPsdsCallback callback); + void setCallback(in IGnssPsdsCallback callback); } \ No newline at end of file diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp index 8c4ee405aa..1fe43c37a4 100644 --- a/gnss/aidl/default/Android.bp +++ b/gnss/aidl/default/Android.bp @@ -17,8 +17,13 @@ cc_binary { name: "android.hardware.gnss-service.example", relative_install_path: "hw", - init_rc: ["gnss-default.rc"], - vintf_fragments: ["gnss-default.xml"], + init_rc: [ + "gnss-default.rc", + ], + vintf_fragments: [ + "gnss-default.xml", + "gnss@2.1-service.xml", + ], vendor: true, cflags: [ "-Wall", @@ -27,12 +32,26 @@ cc_binary { shared_libs: [ "libbase", "libbinder_ndk", + "libhidlbase", + "libutils", "liblog", + "android.hardware.gnss@2.1", + "android.hardware.gnss@2.0", + "android.hardware.gnss@1.1", + "android.hardware.gnss@1.0", + "android.hardware.gnss.measurement_corrections@1.1", + "android.hardware.gnss.measurement_corrections@1.0", + "android.hardware.gnss.visibility_control@1.0", "android.hardware.gnss-ndk_platform", ], srcs: [ "Gnss.cpp", + "GnssHidlHal.cpp", "GnssPsds.cpp", + "GnssConfiguration.cpp", "service.cpp", ], + static_libs: [ + "android.hardware.gnss@common-default-lib", + ], } diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp index 2a359244ef..b4d92fd62f 100644 --- a/gnss/aidl/default/Gnss.cpp +++ b/gnss/aidl/default/Gnss.cpp @@ -18,14 +18,51 @@ #include "Gnss.h" #include +#include "GnssConfiguration.h" #include "GnssPsds.h" namespace aidl::android::hardware::gnss { +std::shared_ptr Gnss::sGnssCallback = nullptr; + +ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr& callback) { + ALOGD("Gnss::setCallback"); + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION); + } + + sGnssCallback = callback; + + int capabilities = (int)IGnssCallback::CAPABILITY_SATELLITE_BLOCKLIST; + auto status = sGnssCallback->gnssSetCapabilitiesCb(capabilities); + if (!status.isOk()) { + ALOGE("%s: Unable to invoke callback.gnssSetCapabilities", __func__); + } + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::close() { + ALOGD("Gnss::close"); + sGnssCallback = nullptr; + return ndk::ScopedAStatus::ok(); +} + ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr* iGnssPsds) { ALOGD("Gnss::getExtensionPsds"); *iGnssPsds = SharedRefBase::make(); return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Gnss::getExtensionGnssConfiguration( + std::shared_ptr* iGnssConfiguration) { + ALOGD("Gnss::getExtensionGnssConfiguration"); + if (mGnssConfiguration == nullptr) { + mGnssConfiguration = SharedRefBase::make(); + } + *iGnssConfiguration = mGnssConfiguration; + return ndk::ScopedAStatus::ok(); +} + } // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h index 9864e9d98c..61d7cf752b 100644 --- a/gnss/aidl/default/Gnss.h +++ b/gnss/aidl/default/Gnss.h @@ -17,12 +17,24 @@ #pragma once #include +#include #include +#include "GnssConfiguration.h" namespace aidl::android::hardware::gnss { class Gnss : public BnGnss { + public: + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + ndk::ScopedAStatus close() override; ndk::ScopedAStatus getExtensionPsds(std::shared_ptr* iGnssPsds) override; + ndk::ScopedAStatus getExtensionGnssConfiguration( + std::shared_ptr* iGnssConfiguration) override; + + std::shared_ptr mGnssConfiguration; + + private: + static std::shared_ptr sGnssCallback; }; } // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssConfiguration.cpp b/gnss/aidl/default/GnssConfiguration.cpp new file mode 100644 index 0000000000..30e0d8c8b9 --- /dev/null +++ b/gnss/aidl/default/GnssConfiguration.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "GnssConfigurationAidl" + +#include "GnssConfiguration.h" +#include + +namespace aidl::android::hardware::gnss { + +ndk::ScopedAStatus GnssConfiguration::setBlocklist(const vector& sourceList) { + ALOGD("GnssConfiguration::setBlocklist"); + std::unique_lock lock(mMutex); + mBlocklistedConstellationSet.clear(); + mBlocklistedSourceSet.clear(); + for (const auto& source : sourceList) { + if (source.svid == 0) { + // Wildcard blocklist, i.e., blocklist entire constellation. + mBlocklistedConstellationSet.insert(source.constellation); + } else { + mBlocklistedSourceSet.insert(source); + } + } + return ndk::ScopedAStatus::ok(); +} + +bool GnssConfiguration::isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const { + std::unique_lock lock(mMutex); + if (mBlocklistedConstellationSet.find(static_cast( + gnssSvInfo.v2_0.constellation)) != mBlocklistedConstellationSet.end()) { + return true; + } + BlocklistedSource source = { + .constellation = static_cast(gnssSvInfo.v2_0.constellation), + .svid = gnssSvInfo.v2_0.v1_0.svid}; + return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end()); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssConfiguration.h b/gnss/aidl/default/GnssConfiguration.h new file mode 100644 index 0000000000..25fa16e610 --- /dev/null +++ b/gnss/aidl/default/GnssConfiguration.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace aidl::android::hardware::gnss { + +using android::hardware::gnss::GnssConstellationType; + +struct BlocklistedSourceHash { + inline int operator()(const BlocklistedSource& source) const { + return int(source.constellation) * 1000 + int(source.svid); + } +}; + +struct BlocklistedSourceEqual { + inline bool operator()(const BlocklistedSource& s1, const BlocklistedSource& s2) const { + return (s1.constellation == s2.constellation) && (s1.svid == s2.svid); + } +}; + +using GnssSvInfoV2_1 = ::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo; +using std::vector; +using BlocklistedSourceSet = + std::unordered_set; +using BlocklistedConstellationSet = std::unordered_set; + +struct GnssConfiguration : public BnGnssConfiguration { + public: + ndk::ScopedAStatus setSuplVersion(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setSuplMode(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setLppProfile(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setGlonassPositioningProtocol(int) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus setEmergencySuplPdn(bool) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setEsExtensionSec(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setBlocklist(const vector& blocklist) override; + + bool isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const; + + private: + BlocklistedSourceSet mBlocklistedSourceSet; + BlocklistedConstellationSet mBlocklistedConstellationSet; + mutable std::recursive_mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssHidlHal.cpp b/gnss/aidl/default/GnssHidlHal.cpp new file mode 100644 index 0000000000..11fc8064fa --- /dev/null +++ b/gnss/aidl/default/GnssHidlHal.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "GnssHidlHal" + +#include "GnssHidlHal.h" +//#include + +namespace aidl::android::hardware::gnss { + +namespace V1_0 = ::android::hardware::gnss::V1_0; + +GnssHidlHal::GnssHidlHal(const std::shared_ptr& gnssAidl) : mGnssAidl(gnssAidl) { + Gnss* iGnss = mGnssAidl.get(); + std::shared_ptr iGnssConfiguration; + auto status = iGnss->getExtensionGnssConfiguration(&iGnssConfiguration); + if (!status.isOk()) { + ALOGE("Failed to getExtensionGnssConfiguration."); + } else { + mGnssConfigurationAidl = iGnss->mGnssConfiguration; + } +}; + +hidl_vec GnssHidlHal::filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList) { + ALOGD("filterBlocklistSatellitesV2_1 - overridden by GnssHidlHal class"); + if (mGnssConfigurationAidl == nullptr) { + ALOGE("Handle to AIDL GnssConfiguration is not available."); + return gnssSvInfoList; + } + for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { + if (mGnssConfigurationAidl->isBlocklistedV2_1(gnssSvInfoList[i])) { + ALOGD("Blocklisted constellation: %d, svid: %d", + (int)gnssSvInfoList[i].v2_0.constellation, gnssSvInfoList[i].v2_0.v1_0.svid); + gnssSvInfoList[i].v2_0.v1_0.svFlag &= + ~static_cast(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX); + } + } + return gnssSvInfoList; +} + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssHidlHal.h b/gnss/aidl/default/GnssHidlHal.h new file mode 100644 index 0000000000..50aad3a206 --- /dev/null +++ b/gnss/aidl/default/GnssHidlHal.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Gnss.h" +#include "GnssConfiguration.h" +#include "v2_1/GnssTemplate.h" + +namespace aidl::android::hardware::gnss { + +using ::android::hardware::gnss::common::implementation::GnssTemplate; +using GnssSvInfo = ::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo; + +class GnssHidlHal : public GnssTemplate<::android::hardware::gnss::V2_1::IGnss> { + public: + GnssHidlHal(const std::shared_ptr& gnssAidl); + + private: + hidl_vec filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList) override; + + std::shared_ptr mGnssAidl; + std::shared_ptr mGnssConfigurationAidl; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssPsds.cpp b/gnss/aidl/default/GnssPsds.cpp index c354217ebe..6512af610a 100644 --- a/gnss/aidl/default/GnssPsds.cpp +++ b/gnss/aidl/default/GnssPsds.cpp @@ -17,27 +17,28 @@ #define LOG_TAG "GnssPsdsAidl" #include "GnssPsds.h" - +#include #include namespace aidl::android::hardware::gnss { std::shared_ptr GnssPsds::sCallback = nullptr; -ndk::ScopedAStatus GnssPsds::setCallback(const std::shared_ptr& callback, - bool* success) { +ndk::ScopedAStatus GnssPsds::setCallback(const std::shared_ptr& callback) { ALOGD("setCallback"); std::unique_lock lock(mMutex); sCallback = callback; - *success = true; return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus GnssPsds::injectPsdsData(PsdsType psdsType, const std::vector& psdsData, - bool* success) { +ndk::ScopedAStatus GnssPsds::injectPsdsData(PsdsType psdsType, + const std::vector& psdsData) { ALOGD("injectPsdsData. psdsType: %d, psdsData: %d bytes", static_cast(psdsType), static_cast(psdsData.size())); - *success = (psdsData.size() > 0); - return ndk::ScopedAStatus::ok(); + if (psdsData.size() > 0) { + return ndk::ScopedAStatus::ok(); + } else { + return ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_INVALID_ARGUMENT); + } } } // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssPsds.h b/gnss/aidl/default/GnssPsds.h index fc65bc15db..de9e68f745 100644 --- a/gnss/aidl/default/GnssPsds.h +++ b/gnss/aidl/default/GnssPsds.h @@ -22,10 +22,9 @@ namespace aidl::android::hardware::gnss { struct GnssPsds : public BnGnssPsds { public: - ndk::ScopedAStatus setCallback(const std::shared_ptr& callback, - bool* success) override; - ndk::ScopedAStatus injectPsdsData(PsdsType psdsType, const std::vector& psdsData, - bool* success) override; + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + ndk::ScopedAStatus injectPsdsData(PsdsType psdsType, + const std::vector& psdsData) override; private: // Guarded by mMutex diff --git a/gnss/aidl/default/gnss@2.1-service.xml b/gnss/aidl/default/gnss@2.1-service.xml new file mode 100644 index 0000000000..12a1fdfa08 --- /dev/null +++ b/gnss/aidl/default/gnss@2.1-service.xml @@ -0,0 +1,12 @@ + + + android.hardware.gnss + hwbinder + 2.1 + 1.1 + + IGnss + default + + + diff --git a/gnss/aidl/default/service.cpp b/gnss/aidl/default/service.cpp index c79a2718c5..09f1ad2b36 100644 --- a/gnss/aidl/default/service.cpp +++ b/gnss/aidl/default/service.cpp @@ -14,22 +14,45 @@ * limitations under the License. */ -#include "Gnss.h" +#define LOG_TAG "Gnss-main" #include #include #include +#include +#include +#include +#include +#include "Gnss.h" +#include "GnssHidlHal.h" using aidl::android::hardware::gnss::Gnss; +using aidl::android::hardware::gnss::GnssHidlHal; +using ::android::OK; +using ::android::sp; +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::gnss::V2_1::IGnss; int main() { - ABinderProcess_setThreadPoolMaxThreadCount(0); - std::shared_ptr vib = ndk::SharedRefBase::make(); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + std::shared_ptr gnssAidl = ndk::SharedRefBase::make(); const std::string instance = std::string() + Gnss::descriptor + "/default"; - binder_status_t status = AServiceManager_addService(vib->asBinder().get(), instance.c_str()); + binder_status_t status = + AServiceManager_addService(gnssAidl->asBinder().get(), instance.c_str()); CHECK(status == STATUS_OK); + sp gnss = new GnssHidlHal(gnssAidl); + configureRpcThreadpool(1, true /* will join */); + if (gnss->registerAsService() != OK) { + ALOGE("Could not register gnss 2.1 service."); + return 0; + } + + joinRpcThreadpool(); ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach } diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp index e57b421768..7f3e5ef339 100644 --- a/gnss/aidl/vts/Android.bp +++ b/gnss/aidl/vts/Android.bp @@ -18,14 +18,22 @@ cc_test { "VtsHalTargetTestDefaults", "use_libaidlvintf_gtest_helper_static", ], - srcs: ["VtsHalGnssTargetTest.cpp"], + srcs: [ + "gnss_hal_test.cpp", + "gnss_hal_test_cases.cpp", + "GnssCallbackAidl.cpp", + "VtsHalGnssTargetTest.cpp", + ], shared_libs: [ + "android.hardware.gnss@2.1", "libbinder", ], static_libs: [ "android.hardware.gnss-cpp", + "android.hardware.gnss@common-vts-lib", ], test_suites: [ + "general-tests", "vts", ], } diff --git a/gnss/aidl/vts/GnssCallbackAidl.cpp b/gnss/aidl/vts/GnssCallbackAidl.cpp new file mode 100644 index 0000000000..f5c745b75c --- /dev/null +++ b/gnss/aidl/vts/GnssCallbackAidl.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "GnssCallbackAidl.h" +#include + +android::binder::Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) { + ALOGI("Capabilities received %d", capabilities); + capabilities_cbq_.store(capabilities); + return android::binder::Status::ok(); +} diff --git a/gnss/aidl/vts/GnssCallbackAidl.h b/gnss/aidl/vts/GnssCallbackAidl.h new file mode 100644 index 0000000000..7f802ea02e --- /dev/null +++ b/gnss/aidl/vts/GnssCallbackAidl.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include +#include "GnssCallbackEventQueue.h" + +/* Callback class for data & Event. */ +class GnssCallbackAidl : public android::hardware::gnss::BnGnssCallback { + public: + GnssCallbackAidl() : capabilities_cbq_("capabilities"){}; + ~GnssCallbackAidl(){}; + + android::binder::Status gnssSetCapabilitiesCb(const int capabilities) override; + + int last_capabilities_; + android::hardware::gnss::common::GnssCallbackEventQueue capabilities_cbq_; +}; \ No newline at end of file diff --git a/gnss/aidl/vts/VtsHalGnssTargetTest.cpp b/gnss/aidl/vts/VtsHalGnssTargetTest.cpp index e7ffc05156..4bba92b49b 100644 --- a/gnss/aidl/vts/VtsHalGnssTargetTest.cpp +++ b/gnss/aidl/vts/VtsHalGnssTargetTest.cpp @@ -13,60 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include -#include + +#include "gnss_hal_test.h" #include -#include #include #include using android::ProcessState; -using android::sp; -using android::String16; -using android::binder::Status; -using android::hardware::gnss::IGnss; -using android::hardware::gnss::IGnssPsds; -using android::hardware::gnss::PsdsType; -class GnssAidlHalTest : public testing::TestWithParam { - public: - virtual void SetUp() override { - gnss_hal_ = android::waitForDeclaredService(String16(GetParam().c_str())); - ASSERT_NE(gnss_hal_, nullptr); - } - - sp gnss_hal_; -}; - -/* - * SetupTeardownCreateCleanup: - * Requests the gnss HAL then calls cleanup - * - * Empty test fixture to verify basic Setup & Teardown - */ -TEST_P(GnssAidlHalTest, SetupTeardownCreateCleanup) {} - -/* - * TestPsdsExtension: - * 1. Gets the PsdsExtension and verifies that it returns a non-null extension. - * 2. Injects empty PSDS data and verifies that it returns false. - */ -TEST_P(GnssAidlHalTest, TestPsdsExtension) { - sp iGnssPsds; - auto status = gnss_hal_->getExtensionPsds(&iGnssPsds); - ASSERT_TRUE(status.isOk()); - ASSERT_TRUE(iGnssPsds != nullptr); - - bool success; - status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector(), &success); - ASSERT_TRUE(status.isOk()); - ASSERT_FALSE(success); -} - -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssAidlHalTest); -INSTANTIATE_TEST_SUITE_P(, GnssAidlHalTest, - testing::ValuesIn(android::getAidlHalInstanceNames(IGnss::descriptor)), +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GnssHalTest); +INSTANTIATE_TEST_SUITE_P(, GnssHalTest, + testing::ValuesIn(android::getAidlHalInstanceNames(IGnssAidl::descriptor)), android::PrintInstanceNameToString); int main(int argc, char** argv) { diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp new file mode 100644 index 0000000000..2447bf8c84 --- /dev/null +++ b/gnss/aidl/vts/gnss_hal_test.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "gnss_hal_test.h" +#include + +using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType; + +void GnssHalTest::SetUp() { + // Get AIDL handle + aidl_gnss_hal_ = android::waitForDeclaredService(String16(GetParam().c_str())); + ASSERT_NE(aidl_gnss_hal_, nullptr); + + const auto& hidlInstanceNames = android::hardware::getAllHalInstanceNames( + android::hardware::gnss::V2_1::IGnss::descriptor); + gnss_hal_ = IGnss_V2_1::getService(hidlInstanceNames[0]); + ASSERT_NE(gnss_hal_, nullptr); + + SetUpGnssCallback(); +} + +void GnssHalTest::SetUpGnssCallback() { + aidl_gnss_cb_ = new GnssCallbackAidl(); + ASSERT_NE(aidl_gnss_cb_, nullptr); + + auto status = aidl_gnss_hal_->setCallback(aidl_gnss_cb_); + if (!status.isOk()) { + ALOGE("Failed to setCallback"); + } + + ASSERT_TRUE(status.isOk()); + + /* + * Capabilities callback should trigger. + */ + EXPECT_TRUE(aidl_gnss_cb_->capabilities_cbq_.retrieve(aidl_gnss_cb_->last_capabilities_, + TIMEOUT_SEC)); + + EXPECT_EQ(aidl_gnss_cb_->capabilities_cbq_.calledCount(), 1); + + // Invoke the super method. + GnssHalTestTemplate::SetUpGnssCallback(); +} diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h new file mode 100644 index 0000000000..eb5301e2cd --- /dev/null +++ b/gnss/aidl/vts/gnss_hal_test.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include +#include + +#include +#include + +#include +#include "GnssCallbackAidl.h" +#include "v2_1/gnss_hal_test_template.h" + +using IGnss_V2_1 = android::hardware::gnss::V2_1::IGnss; + +using android::ProcessState; +using android::sp; +using android::String16; +using IGnssAidl = android::hardware::gnss::IGnss; +using android::hardware::gnss::BlocklistedSource; +using android::hardware::gnss::IGnssConfiguration; + +// The main test class for GNSS HAL. +class GnssHalTest : public GnssHalTestTemplate { + public: + GnssHalTest(){}; + ~GnssHalTest(){}; + virtual void SetUp() override; + virtual void SetUpGnssCallback() override; + + sp aidl_gnss_hal_; + sp aidl_gnss_cb_; // Primary callback interface +}; diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp new file mode 100644 index 0000000000..2b8a447206 --- /dev/null +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "GnssHalTestCases" + +#include +#include "gnss_hal_test.h" + +using android::sp; +using android::hardware::gnss::BlocklistedSource; +using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType; +using android::hardware::gnss::IGnssConfiguration; +using android::hardware::gnss::IGnssPsds; +using android::hardware::gnss::PsdsType; + +/* + * SetupTeardownCreateCleanup: + * Requests the gnss HAL then calls cleanup + * + * Empty test fixture to verify basic Setup & Teardown + */ +TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {} + +/* + * TestPsdsExtension: + * 1. Gets the PsdsExtension and verifies that it returns a non-null extension. + * 2. Injects empty PSDS data and verifies that it returns false. + */ +TEST_P(GnssHalTest, TestPsdsExtension) { + sp iGnssPsds; + auto status = aidl_gnss_hal_->getExtensionPsds(&iGnssPsds); + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(iGnssPsds != nullptr); + + status = iGnssPsds->injectPsdsData(PsdsType::LONG_TERM, std::vector()); + ASSERT_TRUE(status.isOk()); +} + +/* + * FindStrongFrequentNonGpsSource: + * + * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times + * + * returns the strongest source, + * or a source with constellation == UNKNOWN if none are found sufficient times + */ +BlocklistedSource FindStrongFrequentNonGpsSource( + const std::list> sv_info_list, + const int min_observations) { + struct ComparableBlocklistedSource { + BlocklistedSource id; + + ComparableBlocklistedSource() { + id.constellation = GnssConstellationTypeAidl::UNKNOWN; + id.svid = 0; + } + + bool operator<(const ComparableBlocklistedSource& compare) const { + return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) && + (id.constellation < compare.id.constellation))); + } + }; + + struct SignalCounts { + int observations; + float max_cn0_dbhz; + }; + + std::map mapSignals; + + for (const auto& sv_info_vec : sv_info_list) { + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) && + (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) { + ComparableBlocklistedSource source; + source.id.svid = gnss_sv.v2_0.v1_0.svid; + source.id.constellation = + static_cast(gnss_sv.v2_0.constellation); + + const auto& itSignal = mapSignals.find(source); + if (itSignal == mapSignals.end()) { + SignalCounts counts; + counts.observations = 1; + counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz; + mapSignals.insert( + std::pair(source, counts)); + } else { + itSignal->second.observations++; + if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) { + itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz; + } + } + } + } + } + + float max_cn0_dbhz_with_sufficient_count = 0.; + int total_observation_count = 0; + int blocklisted_source_count_observation = 0; + + ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation + for (auto const& pairSignal : mapSignals) { + total_observation_count += pairSignal.second.observations; + if ((pairSignal.second.observations >= min_observations) && + (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) { + source_to_blocklist = pairSignal.first; + blocklisted_source_count_observation = pairSignal.second.observations; + max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz; + } + } + ALOGD("Among %d observations, chose svid %d, constellation %d, " + "with %d observations at %.1f max CNo", + total_observation_count, source_to_blocklist.id.svid, + (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation, + max_cn0_dbhz_with_sufficient_count); + + return source_to_blocklist.id; +} + +/* + * BlocklistIndividualSatellites: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for common satellites (strongest and one other.) + * 2a & b) Turns off location, and blocklists common satellites. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use those satellites. + * 4a & b) Turns off location, and send in empty blocklist. + * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does re-use at least the previously strongest satellite + * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the + * formerly strongest satellite + */ +TEST_P(GnssHalTest, BlocklistIndividualSatellites) { + if (!(aidl_gnss_cb_->last_capabilities_ & + (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) { + ALOGI("Test BlocklistIndividualSatellites skipped. SATELLITE_BLOCKLIST capability not " + "supported."); + return; + } + + const int kLocationsToAwait = 3; + const int kRetriesToUnBlocklist = 10; + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + int location_called_count = gnss_cb_->location_cbq_.calledCount(); + + // Tolerate 1 less sv status to handle edge cases in reporting. + int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", + sv_info_list_cbq_size, kLocationsToAwait, location_called_count); + + /* + * Identify strongest SV seen at least kLocationsToAwait -1 times + * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal + * observability (one epoch RF null) + */ + + const int kGnssSvInfoListTimeout = 2; + std::list> sv_info_vec_list; + int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, + kGnssSvInfoListTimeout); + + ASSERT_EQ(count, sv_info_list_cbq_size); + + BlocklistedSource source_to_blocklist = + FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1); + + if (source_to_blocklist.constellation == GnssConstellationTypeAidl::UNKNOWN) { + // Cannot find a non-GPS satellite. Let the test pass. + ALOGD("Cannot find a non-GPS satellite. Letting the test pass."); + return; + } + + // Stop locations, blocklist the common SV + StopAndClearLocations(); + + sp gnss_configuration_hal; + auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal); + ASSERT_TRUE(status.isOk()); + ASSERT_NE(gnss_configuration_hal, nullptr); + + std::vector sources; + sources.resize(1); + sources[0] = source_to_blocklist; + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + // retry and ensure satellite not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)", + sv_info_list_cbq_size, kLocationsToAwait, location_called_count); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && + (static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + } + } + + // clear blocklist and restart - this time updating the blocklist while location is still on + sources.resize(0); + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + bool strongest_sv_is_reobserved = false; + // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies + int unblocklist_loops_remaining = kRetriesToUnBlocklist; + while (!strongest_sv_is_reobserved && (unblocklist_loops_remaining-- > 0)) { + StopAndClearLocations(); + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit loop if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Clear blocklist, observed %d GnssSvInfo, while awaiting %d Locations" + ", tries remaining %d", + sv_info_list_cbq_size, kLocationsToAwait, unblocklist_loops_remaining); + + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) && + (static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) { + strongest_sv_is_reobserved = true; + break; + } + } + if (strongest_sv_is_reobserved) break; + } + } + EXPECT_TRUE(strongest_sv_is_reobserved); + StopAndClearLocations(); +} + +/* + * BlocklistConstellationLocationOff: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for any non-GPS constellations. + * 2a & b) Turns off location, and blocklist first non-GPS constellations. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use any constellation but GPS. + * 4a & b) Clean up by turning off location, and send in empty blocklist. + */ +TEST_P(GnssHalTest, BlocklistConstellationLocationOff) { + if (!(aidl_gnss_cb_->last_capabilities_ & + (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) { + ALOGI("Test BlocklistConstellationLocationOff skipped. SATELLITE_BLOCKLIST capability not " + "supported."); + return; + } + + const int kLocationsToAwait = 3; + const int kGnssSvInfoListTimeout = 2; + + // Find first non-GPS constellation to blocklist + GnssConstellationTypeAidl constellation_to_blocklist = static_cast( + startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout)); + + // Turns off location + StopAndClearLocations(); + + BlocklistedSource source_to_blocklist_1; + source_to_blocklist_1.constellation = constellation_to_blocklist; + source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation + + // IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is + // supported. + BlocklistedSource source_to_blocklist_2; + source_to_blocklist_2.constellation = GnssConstellationTypeAidl::IRNSS; + source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation + + sp gnss_configuration_hal; + auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal); + ASSERT_TRUE(status.isOk()); + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(2); + sources[0] = source_to_blocklist_1; + sources[1] = source_to_blocklist_2; + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + // retry and ensure constellation not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // Tolerate 1 less sv status to handle edge cases in reporting. + int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size, + kLocationsToAwait); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_1.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_2.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + } + } + + // clean up + StopAndClearLocations(); + sources.resize(0); + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); +} + +/* + * BlocklistConstellationLocationOn: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for any non-GPS constellations. + * 2a & b) Blocklist first non-GPS constellation, and turn off location. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use any constellation but GPS. + * 4a & b) Clean up by turning off location, and send in empty blocklist. + */ +TEST_P(GnssHalTest, BlocklistConstellationLocationOn) { + if (!(aidl_gnss_cb_->last_capabilities_ & + (int)GnssCallbackAidl::CAPABILITY_SATELLITE_BLOCKLIST)) { + ALOGI("Test BlocklistConstellationLocationOn skipped. SATELLITE_BLOCKLIST capability not " + "supported."); + return; + } + + const int kLocationsToAwait = 3; + const int kGnssSvInfoListTimeout = 2; + + // Find first non-GPS constellation to blocklist + GnssConstellationTypeAidl constellation_to_blocklist = static_cast( + startLocationAndGetNonGpsConstellation(kLocationsToAwait, kGnssSvInfoListTimeout)); + + BlocklistedSource source_to_blocklist_1; + source_to_blocklist_1.constellation = constellation_to_blocklist; + source_to_blocklist_1.svid = 0; // documented wildcard for all satellites in this constellation + + // IRNSS was added in 2.0. Always attempt to blocklist IRNSS to verify that the new enum is + // supported. + BlocklistedSource source_to_blocklist_2; + source_to_blocklist_2.constellation = GnssConstellationTypeAidl::IRNSS; + source_to_blocklist_2.svid = 0; // documented wildcard for all satellites in this constellation + + sp gnss_configuration_hal; + auto status = aidl_gnss_hal_->getExtensionGnssConfiguration(&gnss_configuration_hal); + ASSERT_TRUE(status.isOk()); + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(2); + sources[0] = source_to_blocklist_1; + sources[1] = source_to_blocklist_2; + + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); + + // Turns off location + StopAndClearLocations(); + + // retry and ensure constellation not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // Tolerate 1 less sv status to handle edge cases in reporting. + int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size, + kLocationsToAwait); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec sv_info_vec; + gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout); + for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) { + const auto& gnss_sv = sv_info_vec[iSv]; + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_1.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + EXPECT_FALSE((static_cast(gnss_sv.v2_0.constellation) == + source_to_blocklist_2.constellation) && + (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)); + } + } + + // clean up + StopAndClearLocations(); + sources.resize(0); + status = gnss_configuration_hal->setBlocklist(sources); + ASSERT_TRUE(status.isOk()); +} diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h index 1fe6c3eb87..0128df4812 100644 --- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h +++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h @@ -127,12 +127,13 @@ struct GnssTemplate : public T_IGnss { std::atomic mMinIntervalMs; sp mGnssConfiguration; std::atomic mIsActive; - std::atomic mHardwareModeOn; + std::atomic mHardwareModeChecked; std::atomic mGnssFd; std::thread mThread; mutable std::mutex mMutex; - hidl_vec filterBlacklistedSatellitesV2_1(hidl_vec gnssSvInfoList); + virtual hidl_vec filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList); }; template @@ -148,7 +149,7 @@ template GnssTemplate::GnssTemplate() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()}, - mHardwareModeOn(false), + mHardwareModeChecked(false), mGnssFd(-1) {} template @@ -159,16 +160,18 @@ GnssTemplate::~GnssTemplate() { template std::unique_ptr GnssTemplate::getLocationFromHW() { char inputBuffer[INPUT_BUFFER_SIZE]; - if (mGnssFd == -1) { + if (!mHardwareModeChecked) { mGnssFd = open(GNSS_PATH, O_RDWR | O_NONBLOCK); + if (mGnssFd == -1) { + ALOGW("Failed to open /dev/gnss0 errno: %d", errno); + } + mHardwareModeChecked = true; } if (mGnssFd == -1) { - ALOGW("Failed to open /dev/gnss0 errno: %d", errno); return nullptr; } - // Indicates it is a hardwareMode, don't report the default location. - mHardwareModeOn = true; + int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION)); if (bytes_write <= 0) { return nullptr; @@ -206,14 +209,12 @@ Return GnssTemplate::start() { mIsActive = true; mThread = std::thread([this]() { while (mIsActive == true) { - auto svStatus = filterBlacklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1()); + auto svStatus = filterBlocklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1()); this->reportSvStatus(svStatus); auto currentLocation = getLocationFromHW(); - if (mHardwareModeOn) { - if (currentLocation != nullptr) { - // Only report location if the return from hardware is valid - this->reportLocation(*currentLocation); - } + if (mGnssFd != -1 && currentLocation != nullptr) { + // Only report location if the return from hardware is valid + this->reportLocation(*currentLocation); } else { if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) { const auto location = Utils::getMockLocationV2_0(); @@ -230,8 +231,9 @@ Return GnssTemplate::start() { } template -hidl_vec GnssTemplate::filterBlacklistedSatellitesV2_1( +hidl_vec GnssTemplate::filterBlocklistedSatellitesV2_1( hidl_vec gnssSvInfoList) { + ALOGD("filterBlocklistedSatellitesV2_1"); for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) { gnssSvInfoList[i].v2_0.v1_0.svFlag &= diff --git a/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h b/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h index d057c617be..1439158266 100644 --- a/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h +++ b/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h @@ -119,7 +119,7 @@ class GnssHalTestTemplate : public testing::TestWithParam { * SetUpGnssCallback: * Set GnssCallback and verify the result. */ - void SetUpGnssCallback(); + virtual void SetUpGnssCallback(); /* * StartAndCheckFirstLocation: