Merge "Convert VtsHalGraphicsComposerV2_2TargetTest to be parameterized test"
diff --git a/bluetooth/audio/2.0/vts/functional/Android.bp b/bluetooth/audio/2.0/vts/functional/Android.bp
index b672fe4..b778b97 100644
--- a/bluetooth/audio/2.0/vts/functional/Android.bp
+++ b/bluetooth/audio/2.0/vts/functional/Android.bp
@@ -9,4 +9,5 @@
shared_libs: [
"libfmq",
],
+ test_suites: ["general-tests", "vts-core"],
}
diff --git a/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
index 9572d3f..b3cb6f7 100644
--- a/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
+++ b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
@@ -21,12 +21,13 @@
#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h>
#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <hidl/MQDescriptor.h>
+#include <hidl/ServiceManagement.h>
#include <utils/Log.h>
#include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
using ::android::sp;
using ::android::hardware::hidl_vec;
@@ -105,34 +106,13 @@
}
} // namespace
-// Test environment for Bluetooth Audio HAL.
-class BluetoothAudioHidlEnvironment
- : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static BluetoothAudioHidlEnvironment* Instance() {
- static BluetoothAudioHidlEnvironment* instance =
- new BluetoothAudioHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override {
- registerTestService<IBluetoothAudioProvidersFactory>();
- }
-
- private:
- BluetoothAudioHidlEnvironment() {}
-};
-
// The base test class for Bluetooth Audio HAL.
class BluetoothAudioProvidersFactoryHidlTest
- : public ::testing::VtsHalHidlTargetTestBase {
+ : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
- providers_factory_ = ::testing::VtsHalHidlTargetTestBase::getService<
- IBluetoothAudioProvidersFactory>(
- BluetoothAudioHidlEnvironment::Instance()
- ->getServiceName<IBluetoothAudioProvidersFactory>());
+ providers_factory_ =
+ IBluetoothAudioProvidersFactory::getService(GetParam());
ASSERT_NE(providers_factory_, nullptr);
}
@@ -300,13 +280,13 @@
/**
* Test whether we can get the FactoryService from HIDL
*/
-TEST_F(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {}
+TEST_P(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {}
/**
* Test whether we can open a provider for each provider returned by
* getProviderCapabilities() with non-empty capabalities
*/
-TEST_F(BluetoothAudioProvidersFactoryHidlTest,
+TEST_P(BluetoothAudioProvidersFactoryHidlTest,
OpenProviderAndCheckCapabilitiesBySession) {
for (auto session_type : session_types_) {
GetProviderCapabilitiesHelper(session_type);
@@ -341,14 +321,14 @@
/**
* Test whether we can open a provider of type
*/
-TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {}
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {}
/**
* Test whether each provider of type
* SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
* different PCM config
*/
-TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest,
StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
bool is_codec_config_valid;
std::unique_ptr<DataMQ> tempDataMQ;
@@ -616,14 +596,14 @@
/**
* Test whether we can open a provider of type
*/
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {}
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {}
/**
* Test whether each provider of type
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
* SBC hardware encoding config
*/
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
StartAndEndA2dpSbcHardwareSession) {
if (!IsOffloadSupported()) {
return;
@@ -658,7 +638,7 @@
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
* AAC hardware encoding config
*/
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
StartAndEndA2dpAacHardwareSession) {
if (!IsOffloadSupported()) {
return;
@@ -693,7 +673,7 @@
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
* LDAC hardware encoding config
*/
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
StartAndEndA2dpLdacHardwareSession) {
if (!IsOffloadSupported()) {
return;
@@ -728,7 +708,7 @@
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
* AptX hardware encoding config
*/
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
StartAndEndA2dpAptxHardwareSession) {
if (!IsOffloadSupported()) {
return;
@@ -767,7 +747,7 @@
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
* an invalid codec config
*/
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
if (!IsOffloadSupported()) {
return;
@@ -857,7 +837,7 @@
* SessionType::HEARING_AID_HARDWARE_ENCODING_DATAPATH can be started and
* stopped with SBC hardware encoding config
*/
-TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
OpenHearingAidSoftwareProvider) {}
/**
@@ -865,7 +845,7 @@
* SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
* stopped with different PCM config
*/
-TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
StartAndEndHearingAidSessionWithPossiblePcmConfig) {
bool is_codec_config_valid;
std::unique_ptr<DataMQ> tempDataMQ;
@@ -904,12 +884,25 @@
} // SampleRate
}
-int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(
- BluetoothAudioHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- BluetoothAudioHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
- return status;
-}
+static const std::vector<std::string> kAudioInstances =
+ android::hardware::getAllHalInstanceNames(
+ IBluetoothAudioProvidersFactory::descriptor);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProvidersFactoryHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderA2dpSoftwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderA2dpHardwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderHearingAidSoftwareHidlTest,
+ testing::ValuesIn(kAudioInstances),
+ android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c6fd76e..aecc4e0 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -155,7 +155,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.drm</name>
- <version>1.0-2</version>
+ <version>1.0-3</version>
<interface>
<name>ICryptoFactory</name>
<regex-instance>.*</regex-instance>
@@ -189,7 +189,7 @@
- test DeviceManifestTest#GnssHalVersionCompatibility.
-->
<version>1.1</version>
- <version>2.0</version>
+ <version>2.0-1</version>
<interface>
<name>IGnss</name>
<instance>default</instance>
diff --git a/current.txt b/current.txt
index 22db077..940575e 100644
--- a/current.txt
+++ b/current.txt
@@ -593,6 +593,12 @@
9811f867def49b420d8c707f7e38d3bdd64f835244e1d2a5e9762ab9835672dc android.hardware.cas@1.2::ICasListener
f18695dd36ee205640b8326a17453858a7b4596653aaa6ef0016b0aef1bd4dac android.hardware.cas@1.2::IMediaCasService
4d85e814f94949dae4dc6cb82bbd7d6bb24ffafda6ddb2eac928d2a4fc2e21ce android.hardware.cas@1.2::types
+66931c2506fbb5af61f20138cb05e0a09e7bf67d6964c231d27c648933bb33ec android.hardware.drm@1.3::ICryptoFactory
+994d08ab27d613022c258a9ec48cece7adf2a305e92df5d76ef923e2c6665f64 android.hardware.drm@1.3::IDrmFactory
+1bd8028b974bf1d65cfa102196a2b008afc5d42fe73fed2cb94fa7533d07f581 android.hardware.gnss@2.1::IGnss
+ba62e1e8993bfb9f27fa04816fa0f2241ae2d01edfa3d0c04182e2e5de80045c android.hardware.gnss@2.1::IGnssCallback
+5a125c49ca83629e22afc8c39e865509343bfa2c38f0baea9a186bbac103492d android.hardware.gnss@2.1::IGnssMeasurement
+0bfb291708dd4a7c6ec6b9883e2b8592357edde8d7e962ef83918e4a2154ce69 android.hardware.gnss@2.1::IGnssMeasurementCallback
ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
26f04510a0b57aba5167c5c0a7c2f077c2acbb98b81902a072517829fd9fd67f android.hardware.health@2.1::IHealthInfoCallback
db47f4ceceb1f06c656f39caa70c557b0f8471ef59fd58611bea667ffca20101 android.hardware.health@2.1::types
@@ -611,12 +617,11 @@
619fc9839ec6e369cfa9b28e3e9412e6885720ff8f9b5750c1b6ffb905120391 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
c9273429fcf98d797d3bb07fdba6f1be95bf960f9255cde169fd1ca4db85f856 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
9b0a3ab6f4f74b971ed094426d8a443e29b512ff03e1ab50c07156396cdb2483 android.hardware.wifi.supplicant@1.3::types
-274fb1254a6d1a97824ec5c880eeefc0e410dc6d3a2a4c34052201169d2b7de0 android.hardware.radio@1.5::types
-4c666aaf3944ad91c2428b8456d0db4a2f81191f8c294f046a2f539e9fc7b6fd android.hardware.radio@1.5::IRadio
+521d1fe5b9f212b7b37ab71c0d33f5d2622618837e318e99a80d882f186af6b9 android.hardware.radio@1.5::types
+3f1e2410d9bed4e7d41c6a589fe3a7943bc904b0066e40e0199a7c58427ac4e9 android.hardware.radio@1.5::IRadio
3afac66f21a33bc9c4b80481c7d5540038348651d9a7d8af64ea13610af138da android.hardware.radio@1.5::IRadioIndication
-70e977f2ccefd2e503bedb3a66313639b53fbc7bde025538b07f41e2292b6624 android.hardware.radio@1.5::IRadioResponse
+caf00e0d942b77b17d7061b38de11e5b19e1da90d4818434cb4916ba89e30686 android.hardware.radio@1.5::IRadioResponse
55f0a15642869ec98a55ea0a5ac049d3e1a6245ff7750deb6bcb7182057eee83 android.hardware.radio.config@1.3::types
b27ab0cd40b0b078cdcd024bfe1061c4c4c065f3519eeb9347fa359a3268a5ae android.hardware.radio.config@1.3::IRadioConfig
742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
7683fed9d253956071f18b152e6be657719536f98d9b534433d5e411bcde5061 android.hardware.radio.config@1.3::IRadioConfigResponse
-
diff --git a/drm/1.3/Android.bp b/drm/1.3/Android.bp
new file mode 100644
index 0000000..b0ffcb9
--- /dev/null
+++ b/drm/1.3/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.drm@1.3",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "IDrmFactory.hal",
+ "ICryptoFactory.hal",
+ ],
+ interfaces: [
+ "android.hardware.drm@1.0",
+ "android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
diff --git a/drm/1.3/ICryptoFactory.hal b/drm/1.3/ICryptoFactory.hal
new file mode 100644
index 0000000..d7864eb
--- /dev/null
+++ b/drm/1.3/ICryptoFactory.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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.drm@1.3;
+
+import @1.2::ICryptoFactory;
+
+/**
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
+ * which are used by a codec to decrypt protected video content.
+ *
+ * The 1.3 factory must always create 1.2 ICryptoPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * The ICryptoFactory hal is required because all top-level interfaces
+ * have to be updated in a minor uprev.
+ */
+interface ICryptoFactory extends @1.2::ICryptoFactory {
+};
diff --git a/drm/1.3/IDrmFactory.hal b/drm/1.3/IDrmFactory.hal
new file mode 100644
index 0000000..5208028
--- /dev/null
+++ b/drm/1.3/IDrmFactory.hal
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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.drm@1.3;
+
+import @1.2::IDrmFactory;
+
+/**
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt protected video content.
+ *
+ * The 1.3 factory must always create 1.2 IDrmPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ */
+
+interface IDrmFactory extends @1.2::IDrmFactory {
+ /**
+ * Return vector of uuids identifying crypto schemes supported by this HAL.
+ *
+ * @return schemes Vector of uuids for which isCryptoSchemeSupported is true;
+ * each uuid can be used as input to createPlugin.
+ */
+ getSupportedCryptoSchemes() generates(vec<uint8_t[16]> schemes);
+};
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 95bd7f3..9c498d5 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -14,6 +14,8 @@
"libhidlbase",
"libutils",
"liblog",
+ "android.hardware.gnss@2.1",
+ "android.hardware.gnss@2.0",
"android.hardware.gnss@1.1",
"android.hardware.gnss@1.0",
],
diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp
index 4abe707..5043649 100644
--- a/gnss/1.1/default/Gnss.cpp
+++ b/gnss/1.1/default/Gnss.cpp
@@ -44,7 +44,7 @@
auto svStatus = this->getMockSvStatus();
this->reportSvStatus(svStatus);
- auto location = Utils::getMockLocation();
+ auto location = Utils::getMockLocationV1_0();
this->reportLocation(location);
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
@@ -197,14 +197,14 @@
Return<GnssSvStatus> Gnss::getMockSvStatus() const {
std::unique_lock<std::recursive_mutex> lock(mGnssConfiguration->getMutex());
GnssSvInfo mockGnssSvInfoList[] = {
- Utils::getSvInfo(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5),
- Utils::getSvInfo(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
- Utils::getSvInfo(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
- Utils::getSvInfo(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
- Utils::getSvInfo(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0),
- Utils::getSvInfo(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0),
- Utils::getSvInfo(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0),
- Utils::getSvInfo(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
+ Utils::getMockSvInfoV1_0(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5),
+ Utils::getMockSvInfoV1_0(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
+ Utils::getMockSvInfoV1_0(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
+ Utils::getMockSvInfoV1_0(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
+ Utils::getMockSvInfoV1_0(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0),
+ Utils::getMockSvInfoV1_0(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0),
+ Utils::getMockSvInfoV1_0(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0),
+ Utils::getMockSvInfoV1_0(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)};
for (uint32_t i = 0; i < svStatus.numSvs; i++) {
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 3ba89da..37de55d 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -25,7 +25,7 @@
"AGnss.cpp",
"AGnssRil.cpp",
"Gnss.cpp",
- "GnssBatching.cpp",
+ "GnssBatching.cpp",
"GnssMeasurement.cpp",
"GnssMeasurementCorrections.cpp",
"GnssVisibilityControl.cpp",
@@ -35,9 +35,10 @@
"libhidlbase",
"libutils",
"liblog",
- "android.hardware.gnss@2.0",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.visibility_control@1.0",
+ "android.hardware.gnss@2.1",
+ "android.hardware.gnss@2.0",
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
],
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index 3d64fc3..09f2fc0 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -19,7 +19,6 @@
#include "Gnss.h"
#include <log/log.h>
-#include <utils/SystemClock.h>
#include "AGnss.h"
#include "AGnssRil.h"
@@ -47,24 +46,6 @@
sp<V2_0::IGnssCallback> Gnss::sGnssCallback_2_0 = nullptr;
sp<V1_1::IGnssCallback> Gnss::sGnssCallback_1_1 = nullptr;
-namespace {
-
-V2_0::GnssLocation getMockLocationV2_0() {
- const ElapsedRealtime timestamp = {
- .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
- ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
- .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
- // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
- // In an actual implementation provide an estimate of the synchronization uncertainty
- // or don't set the field.
- .timeUncertaintyNs = 1000000};
-
- V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocation(), .elapsedRealtime = timestamp};
- return location;
-}
-
-} // namespace
-
Gnss::Gnss() : mMinIntervalMs(1000) {}
Gnss::~Gnss() {
@@ -86,7 +67,7 @@
mIsActive = true;
mThread = std::thread([this]() {
while (mIsActive == true) {
- const auto location = getMockLocationV2_0();
+ const auto location = Utils::getMockLocationV2_0();
this->reportLocation(location);
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp
index 1f95ff9..d778d50 100644
--- a/gnss/2.0/default/GnssMeasurement.cpp
+++ b/gnss/2.0/default/GnssMeasurement.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "GnssMeasurement"
#include "GnssMeasurement.h"
+#include "Utils.h"
#include <log/log.h>
#include <utils/SystemClock.h>
@@ -29,6 +30,7 @@
using GnssConstellationType = V2_0::GnssConstellationType;
using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
using GnssMeasurementState = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
+using Utils = common::Utils;
sp<V2_0::IGnssMeasurementCallback> GnssMeasurement::sCallback = nullptr;
@@ -81,7 +83,7 @@
mIsActive = true;
mThread = std::thread([this]() {
while (mIsActive == true) {
- auto measurement = this->getMockMeasurement();
+ auto measurement = Utils::getMockMeasurementV2_0();
this->reportMeasurement(measurement);
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
@@ -97,60 +99,6 @@
}
}
-GnssData GnssMeasurement::getMockMeasurement() {
- V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = {
- .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
- .svid = (int16_t)6,
- .constellation = V1_0::GnssConstellationType::UNKNOWN,
- .timeOffsetNs = 0.0,
- .receivedSvTimeInNs = 8195997131077,
- .receivedSvTimeUncertaintyInNs = 15,
- .cN0DbHz = 30.0,
- .pseudorangeRateMps = -484.13739013671875,
- .pseudorangeRateUncertaintyMps = 1.0379999876022339,
- .accumulatedDeltaRangeState = (uint32_t)V1_0::IGnssMeasurementCallback::
- GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN,
- .accumulatedDeltaRangeM = 0.0,
- .accumulatedDeltaRangeUncertaintyM = 0.0,
- .carrierFrequencyHz = 1.59975e+09,
- .multipathIndicator =
- V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN};
- V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0};
- V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {
- .v1_1 = measurement_1_1,
- .codeType = "C",
- .state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC |
- GnssMeasurementState::STATE_SUBFRAME_SYNC |
- GnssMeasurementState::STATE_TOW_DECODED |
- GnssMeasurementState::STATE_GLO_STRING_SYNC |
- GnssMeasurementState::STATE_GLO_TOD_DECODED,
- .constellation = GnssConstellationType::GLONASS,
- };
-
- hidl_vec<IGnssMeasurementCallback::GnssMeasurement> measurements(1);
- measurements[0] = measurement_2_0;
- V1_0::IGnssMeasurementCallback::GnssClock clock = {.timeNs = 2713545000000,
- .fullBiasNs = -1226701900521857520,
- .biasNs = 0.59689998626708984,
- .biasUncertaintyNs = 47514.989972114563,
- .driftNsps = -51.757811607455452,
- .driftUncertaintyNsps = 310.64968328491528,
- .hwClockDiscontinuityCount = 1};
-
- ElapsedRealtime timestamp = {
- .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
- ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
- .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
- // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
- // In an actual implementation provide an estimate of the synchronization uncertainty
- // or don't set the field.
- .timeUncertaintyNs = 1000000};
-
- GnssData gnssData = {
- .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp};
- return gnssData;
-}
-
void GnssMeasurement::reportMeasurement(const GnssData& data) {
ALOGD("reportMeasurement()");
std::unique_lock<std::mutex> lock(mMutex);
diff --git a/gnss/2.0/default/GnssMeasurement.h b/gnss/2.0/default/GnssMeasurement.h
index c24c00e..d8ffd59 100644
--- a/gnss/2.0/default/GnssMeasurement.h
+++ b/gnss/2.0/default/GnssMeasurement.h
@@ -59,7 +59,6 @@
private:
void start();
void stop();
- GnssData getMockMeasurement();
void reportMeasurement(const GnssData&);
static sp<IGnssMeasurementCallback> sCallback;
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 9aa1334..da5289d 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -28,6 +28,7 @@
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
"android.hardware.gnss@2.0",
+ "android.hardware.gnss@2.1",
"android.hardware.gnss@common-vts-lib",
],
test_suites: ["general-tests", "vts-core"],
diff --git a/gnss/2.1/Android.bp b/gnss/2.1/Android.bp
new file mode 100644
index 0000000..5d3d62d
--- /dev/null
+++ b/gnss/2.1/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.gnss@2.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "IGnss.hal",
+ "IGnssCallback.hal",
+ "IGnssMeasurement.hal",
+ "IGnssMeasurementCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.gnss.measurement_corrections@1.0",
+ "android.hardware.gnss.visibility_control@1.0",
+ "android.hardware.gnss@1.0",
+ "android.hardware.gnss@1.1",
+ "android.hardware.gnss@2.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/gnss/2.1/IGnss.hal b/gnss/2.1/IGnss.hal
new file mode 100644
index 0000000..812f9cc
--- /dev/null
+++ b/gnss/2.1/IGnss.hal
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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@2.1;
+
+import @2.0::IGnss;
+
+import IGnssCallback;
+import IGnssMeasurement;
+
+/**
+ * Represents the standard GNSS (Global Navigation Satellite System) interface.
+ */
+interface IGnss extends @2.0::IGnss {
+ /**
+ * 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.
+ *
+ * @return success Returns true on success.
+ */
+ setCallback_2_1(IGnssCallback callback) generates (bool success);
+
+ /**
+ * This method returns the IGnssMeasurement interface.
+ *
+ * At least one of getExtensionGnssMeasurement(), getExtensionGnssMeasurement_1_1(),
+ * getExtensionGnssMeasurement_2_0(), and getExtensionGnssMeasurement_2_1() methods must return
+ * a non-null handle, and the other methods must return nullptr.
+ *
+ * @return gnssMeasurementIface Handle to the IGnssMeasurement interface.
+ */
+ getExtensionGnssMeasurement_2_1() generates (IGnssMeasurement gnssMeasurementIface);
+};
\ No newline at end of file
diff --git a/gnss/2.1/IGnssCallback.hal b/gnss/2.1/IGnssCallback.hal
new file mode 100644
index 0000000..da70742
--- /dev/null
+++ b/gnss/2.1/IGnssCallback.hal
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 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@2.1;
+
+import @2.0::IGnssCallback;
+
+/**
+ * This interface is required for the HAL to communicate certain information
+ * like status and location info back to the platform, the platform implements
+ * the interfaces and passes a handle to the HAL.
+ */
+interface IGnssCallback extends @2.0::IGnssCallback {
+
+ /** Extends a GnssSvInfo, adding a basebandCN0DbHz. */
+ struct GnssSvInfo {
+ /**
+ * GNSS satellite information for a single satellite and frequency.
+ */
+ @2.0::IGnssCallback.GnssSvInfo v2_0;
+
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This value is mandatory. Like cN0DbHz, it may be reported as 0 for satellites being
+ * reported that may be searched for, but not yet tracked.
+ */
+ double basebandCN0DbHz;
+ };
+
+ /**
+ * Callback for the HAL to pass a vector of GnssSvInfo back to the client.
+ *
+ * @param svInfoList SV info list information from HAL.
+ */
+ gnssSvStatusCb_2_1(vec<GnssSvInfo> svInfoList);
+};
diff --git a/gnss/2.1/IGnssMeasurement.hal b/gnss/2.1/IGnssMeasurement.hal
new file mode 100644
index 0000000..d2c76e6
--- /dev/null
+++ b/gnss/2.1/IGnssMeasurement.hal
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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@2.1;
+
+import @1.0::IGnssMeasurement;
+import @1.1::IGnssMeasurement;
+import @2.0::IGnssMeasurement;
+import IGnssMeasurementCallback;
+
+/**
+ * Extended interface for GNSS Measurements support.
+ */
+interface IGnssMeasurement extends @2.0::IGnssMeasurement {
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL. After a
+ * successful call to 'setCallback_2_1' the HAL must begin to provide updates at an average
+ * output rate of 1Hz (occasional intra-measurement time offsets in the range from 0-2000msec
+ * can be tolerated.)
+ *
+ * @param callback Handle to GnssMeasurement callback interface.
+ * @param enableFullTracking If true, GNSS chipset must switch off duty cycling. In such mode
+ * no clock discontinuities are expected and, when supported, carrier phase should be
+ * continuous in good signal conditions. All non-blacklisted, healthy constellations,
+ * satellites and frequency bands that the chipset supports must be reported in this mode.
+ * The GNSS chipset is allowed to consume more power in this mode. If false, API must behave
+ * as in HAL V1_0, optimizing power via duty cycling, constellations and frequency limits,
+ * etc.
+ *
+ * @return initRet Returns SUCCESS if successful. Returns ERROR_ALREADY_INIT if a callback has
+ * already been registered without a corresponding call to 'close'. Returns ERROR_GENERIC
+ * for any other error. The HAL must not generate any other updates upon returning this
+ * error code.
+ */
+ setCallback_2_1(IGnssMeasurementCallback callback, bool enableFullTracking)
+ generates (GnssMeasurementStatus initRet);
+};
diff --git a/gnss/2.1/IGnssMeasurementCallback.hal b/gnss/2.1/IGnssMeasurementCallback.hal
new file mode 100644
index 0000000..ca6175f
--- /dev/null
+++ b/gnss/2.1/IGnssMeasurementCallback.hal
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 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@2.1;
+
+import @1.0::IGnssMeasurementCallback;
+import @1.1::IGnssMeasurementCallback;
+import @2.0::IGnssMeasurementCallback;
+import @2.0::ElapsedRealtime;
+
+/** The callback interface to report measurements from the HAL. */
+interface IGnssMeasurementCallback extends @2.0::IGnssMeasurementCallback {
+
+ /**
+ * Extends a GNSS Measurement, adding a basebandCN0DbHz.
+ */
+ struct GnssMeasurement {
+ /**
+ * GNSS measurement information for a single satellite and frequency, as in the 2.0 version
+ * of the HAL.
+ */
+ @2.0::IGnssMeasurementCallback.GnssMeasurement v2_0;
+
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This value is mandatory.
+ */
+ double basebandCN0DbHz;
+ };
+
+ /**
+ * Complete set of GNSS Measurement data, same as 2.0 with additional double (i.e.,
+ * basebandCN0DbHz) in measurements.
+ */
+ struct GnssData {
+ /** The full set of satellite measurement observations. */
+ vec<GnssMeasurement> measurements;
+
+ /** The GNSS clock time reading. */
+ GnssClock clock;
+
+ /**
+ * Timing information of the GNSS data synchronized with SystemClock.elapsedRealtimeNanos()
+ * clock.
+ */
+ ElapsedRealtime elapsedRealtime;
+ };
+
+ /**
+ * Callback for the hal to pass a GnssData structure back to the client.
+ *
+ * @param data Contains a reading of GNSS measurements.
+ */
+ gnssMeasurementCb_2_1(GnssData data);
+};
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
new file mode 100644
index 0000000..a7cf63d
--- /dev/null
+++ b/gnss/2.1/default/Android.bp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_binary {
+ name: "android.hardware.gnss@2.1-service",
+ init_rc: ["android.hardware.gnss@2.1-service.rc"],
+ relative_install_path: "hw",
+ vendor: true,
+ vintf_fragments: ["android.hardware.gnss@2.1-service.xml"],
+ srcs: [
+ "Gnss.cpp",
+ "GnssMeasurement.cpp",
+ "service.cpp"
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libutils",
+ "liblog",
+ "android.hardware.gnss.measurement_corrections@1.0",
+ "android.hardware.gnss.visibility_control@1.0",
+ "android.hardware.gnss@2.1",
+ "android.hardware.gnss@1.0",
+ "android.hardware.gnss@1.1",
+ "android.hardware.gnss@2.0",
+ ],
+ static_libs: [
+ "android.hardware.gnss@common-default-lib",
+ ],
+}
diff --git a/gnss/2.1/default/Gnss.cpp b/gnss/2.1/default/Gnss.cpp
new file mode 100644
index 0000000..2771f27
--- /dev/null
+++ b/gnss/2.1/default/Gnss.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2019 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 "Gnss"
+
+#include "Gnss.h"
+#include "GnssMeasurement.h"
+#include "Utils.h"
+
+#include <log/log.h>
+
+using ::android::hardware::gnss::common::Utils;
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+sp<V2_1::IGnssCallback> Gnss::sGnssCallback_2_1 = nullptr;
+
+Gnss::Gnss() : mMinIntervalMs(1000) {}
+
+Gnss::~Gnss() {
+ stop();
+}
+
+Return<bool> Gnss::start() {
+ ALOGD("start");
+ if (mIsActive) {
+ ALOGW("Gnss has started. Restarting...");
+ stop();
+ }
+
+ mIsActive = true;
+ mThread = std::thread([this]() {
+ while (mIsActive == true) {
+ auto svStatus = Utils::getMockSvInfoListV2_1();
+ this->reportSvStatus(svStatus);
+
+ const auto location = Utils::getMockLocationV2_0();
+ this->reportLocation(location);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+ }
+ });
+ return true;
+}
+
+Return<bool> Gnss::stop() {
+ ALOGD("stop");
+ mIsActive = false;
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+ return true;
+}
+
+// Methods from V1_0::IGnss follow.
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>&) {
+ // TODO implement
+ return bool{};
+}
+
+Return<void> Gnss::cleanup() {
+ // TODO implement
+ return Void();
+}
+
+Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
+ // TODO implement
+ return bool{};
+}
+
+Return<bool> Gnss::injectLocation(double, double, float) {
+ // TODO implement
+ return bool{};
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) {
+ // TODO implement
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode,
+ V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t,
+ uint32_t) {
+ // TODO implement
+ return bool{};
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ // TODO implement
+ return ::android::sp<V1_0::IAGnssRil>{};
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssGeofencing>{};
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ // TODO implement
+ return ::android::sp<V1_0::IAGnss>{};
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssNi>{};
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssMeasurement>{};
+}
+
+Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssNavigationMessage>{};
+}
+
+Return<sp<V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssXtra>{};
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssConfiguration>{};
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssDebug>{};
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ // TODO implement
+ return ::android::sp<V1_0::IGnssBatching>{};
+}
+
+// Methods from V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>&) {
+ // TODO implement
+ return bool{};
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode,
+ V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t,
+ uint32_t, bool) {
+ return true;
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+ // TODO implement
+ return ::android::sp<V1_1::IGnssConfiguration>{};
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+ // TODO implement
+ return ::android::sp<V1_1::IGnssMeasurement>{};
+}
+
+Return<bool> Gnss::injectBestLocation(const V1_0::GnssLocation&) {
+ // TODO implement
+ return bool{};
+}
+
+// Methods from V2_0::IGnss follow.
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>&) {
+ // TODO implement
+ return bool{};
+}
+
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+ // TODO implement
+ return ::android::sp<V2_0::IGnssConfiguration>{};
+}
+
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+ // TODO implement
+ return ::android::sp<V2_0::IGnssDebug>{};
+}
+
+Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
+ // TODO implement
+ return ::android::sp<V2_0::IAGnss>{};
+}
+
+Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
+ // TODO implement
+ return ::android::sp<V2_0::IAGnssRil>{};
+}
+
+Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
+ // TODO implement
+ return ::android::sp<V2_0::IGnssMeasurement>{};
+}
+
+Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
+Gnss::getExtensionMeasurementCorrections() {
+ // TODO implement
+ return ::android::sp<measurement_corrections::V1_0::IMeasurementCorrections>{};
+}
+
+Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> Gnss::getExtensionVisibilityControl() {
+ // TODO implement
+ return ::android::sp<visibility_control::V1_0::IGnssVisibilityControl>{};
+}
+
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+ // TODO implement
+ return ::android::sp<V2_0::IGnssBatching>{};
+}
+
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation&) {
+ // TODO implement
+ return bool{};
+}
+
+// Methods from V2_1::IGnss follow.
+Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
+ ALOGD("Gnss::setCallback_2_1");
+ if (callback == nullptr) {
+ ALOGE("%s: Null callback ignored", __func__);
+ return false;
+ }
+
+ sGnssCallback_2_1 = callback;
+
+ using Capabilities = V2_0::IGnssCallback::Capabilities;
+ const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
+ Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
+ auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_0(capabilities);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+
+ V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020};
+
+ ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+
+ auto gnssName = "Android Mock GNSS Implementation v2.1";
+ ret = sGnssCallback_2_1->gnssNameCb(gnssName);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+
+ return true;
+}
+
+Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
+ ALOGD("Gnss::getExtensionGnssMeasurement_2_1");
+ return new GnssMeasurement();
+}
+
+void Gnss::reportSvStatus(const hidl_vec<GnssSvInfo>& svInfoList) const {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sGnssCallback_2_1 == nullptr) {
+ ALOGE("%s: sGnssCallback v2.1 is null.", __func__);
+ return;
+ }
+ auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void Gnss::reportLocation(const V2_0::GnssLocation& location) const {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sGnssCallback_2_1 == nullptr) {
+ ALOGE("%s: sGnssCallback v2.1 is null.", __func__);
+ return;
+ }
+ auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/2.1/default/Gnss.h b/gnss/2.1/default/Gnss.h
new file mode 100644
index 0000000..a61f71c
--- /dev/null
+++ b/gnss/2.1/default/Gnss.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 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 <android/hardware/gnss/2.1/IGnss.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+
+using GnssSvInfo = IGnssCallback::GnssSvInfo;
+
+namespace implementation {
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+ // Methods from V1_0::IGnss follow.
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<bool> injectLocation(double latitudeDegrees, double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
+ Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ // Methods from V1_1::IGnss follow.
+ Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+ Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs, bool lowPowerMode) override;
+ Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+ Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+ Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
+
+ // Methods from V2_0::IGnss follow.
+ Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+ Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+ Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+ Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+ Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+ Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+ Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
+ getExtensionMeasurementCorrections() override;
+ Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
+ override;
+ Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+ Return<bool> injectBestLocation_2_0(const V2_0::GnssLocation& location) override;
+
+ // Methods from V2_1::IGnss follow.
+ Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
+ Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
+
+ private:
+ void reportLocation(const V2_0::GnssLocation&) const;
+ void reportSvStatus(const hidl_vec<GnssSvInfo>&) const;
+
+ static sp<V2_1::IGnssCallback> sGnssCallback_2_1;
+ std::atomic<long> mMinIntervalMs;
+ std::atomic<bool> mIsActive;
+ std::thread mThread;
+ mutable std::mutex mMutex;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/2.1/default/GnssMeasurement.cpp b/gnss/2.1/default/GnssMeasurement.cpp
new file mode 100644
index 0000000..ebfa7dd
--- /dev/null
+++ b/gnss/2.1/default/GnssMeasurement.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2019 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 "GnssMeasurement"
+
+#include "GnssMeasurement.h"
+#include <log/log.h>
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+
+using common::Utils;
+
+namespace V2_1 {
+namespace implementation {
+
+sp<V2_1::IGnssMeasurementCallback> GnssMeasurement::sCallback = nullptr;
+
+GnssMeasurement::GnssMeasurement() : mMinIntervalMillis(1000) {}
+
+GnssMeasurement::~GnssMeasurement() {
+ stop();
+}
+
+// Methods from V1_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>&) {
+ // TODO implement
+ return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
+}
+
+Return<void> GnssMeasurement::close() {
+ ALOGD("close");
+ std::unique_lock<std::mutex> lock(mMutex);
+ stop();
+ sCallback = nullptr;
+ return Void();
+}
+
+// Methods from V1_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>&, bool) {
+ // TODO implement
+ return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
+}
+
+// Methods from V2_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>&, bool) {
+ // TODO implement
+ return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
+}
+
+// Methods from V2_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_1(
+ const sp<V2_1::IGnssMeasurementCallback>& callback, bool) {
+ ALOGD("setCallback_2_1");
+ std::unique_lock<std::mutex> lock(mMutex);
+ sCallback = callback;
+
+ if (mIsActive) {
+ ALOGW("GnssMeasurement callback already set. Resetting the callback...");
+ stop();
+ }
+ start();
+
+ return V1_0::IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+void GnssMeasurement::start() {
+ ALOGD("start");
+ mIsActive = true;
+ mThread = std::thread([this]() {
+ while (mIsActive == true) {
+ auto measurement = Utils::getMockMeasurementV2_1();
+ this->reportMeasurement(measurement);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
+ }
+ });
+}
+
+void GnssMeasurement::stop() {
+ ALOGD("stop");
+ mIsActive = false;
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void GnssMeasurement::reportMeasurement(const GnssDataV2_1& data) {
+ ALOGD("reportMeasurement()");
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sCallback == nullptr) {
+ ALOGE("%s: GnssMeasurement::sCallback is null.", __func__);
+ return;
+ }
+ auto ret = sCallback->gnssMeasurementCb_2_1(data);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/2.1/default/GnssMeasurement.h b/gnss/2.1/default/GnssMeasurement.h
new file mode 100644
index 0000000..ee32903
--- /dev/null
+++ b/gnss/2.1/default/GnssMeasurement.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 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 <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData;
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct GnssMeasurement : public IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+ // Methods from V1_0::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ // Methods from V1_1::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
+
+ // Methods from V2_0::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
+
+ // Methods from V2_1::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_1(
+ const sp<V2_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
+
+ private:
+ void start();
+ void stop();
+ void reportMeasurement(const GnssDataV2_1&);
+
+ static sp<IGnssMeasurementCallback> sCallback;
+ std::atomic<long> mMinIntervalMillis;
+ std::atomic<bool> mIsActive;
+ std::thread mThread;
+ mutable std::mutex mMutex;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/2.1/default/OWNERS b/gnss/2.1/default/OWNERS
new file mode 100644
index 0000000..b7b4a2e
--- /dev/null
+++ b/gnss/2.1/default/OWNERS
@@ -0,0 +1,4 @@
+gomo@google.com
+smalkos@google.com
+wyattriley@google.com
+yuhany@google.com
diff --git a/gnss/2.1/default/android.hardware.gnss@2.1-service.rc b/gnss/2.1/default/android.hardware.gnss@2.1-service.rc
new file mode 100644
index 0000000..5926c77
--- /dev/null
+++ b/gnss/2.1/default/android.hardware.gnss@2.1-service.rc
@@ -0,0 +1,4 @@
+service vendor.gnss-2-1 /vendor/bin/hw/android.hardware.gnss@2.1-service
+ class hal
+ user system
+ group system
diff --git a/gnss/2.1/default/android.hardware.gnss@2.1-service.xml b/gnss/2.1/default/android.hardware.gnss@2.1-service.xml
new file mode 100644
index 0000000..12a1fdf
--- /dev/null
+++ b/gnss/2.1/default/android.hardware.gnss@2.1-service.xml
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <version>1.1</version>
+ <interface>
+ <name>IGnss</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/gnss/2.1/default/service.cpp b/gnss/2.1/default/service.cpp
new file mode 100644
index 0000000..5e004d5
--- /dev/null
+++ b/gnss/2.1/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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 "android.hardware.gnss@2.1-service"
+
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include "Gnss.h"
+
+using ::android::OK;
+using ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::gnss::V2_1::IGnss;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+
+int main(int /* argc */, char* /* argv */[]) {
+ sp<IGnss> gnss = new Gnss();
+ configureRpcThreadpool(1, true /* will join */);
+ if (gnss->registerAsService() != OK) {
+ ALOGE("Could not register gnss 2.1 service.");
+ return 1;
+ }
+ joinRpcThreadpool();
+
+ ALOGE("Service exited!");
+ return 1;
+}
\ No newline at end of file
diff --git a/gnss/2.1/vts/OWNERS b/gnss/2.1/vts/OWNERS
new file mode 100644
index 0000000..b7b4a2e
--- /dev/null
+++ b/gnss/2.1/vts/OWNERS
@@ -0,0 +1,4 @@
+gomo@google.com
+smalkos@google.com
+wyattriley@google.com
+yuhany@google.com
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
new file mode 100644
index 0000000..8340499
--- /dev/null
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_test {
+ name: "VtsHalGnssV2_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "gnss_hal_test.cpp",
+ "gnss_hal_test_cases.cpp",
+ "VtsHalGnssV2_1TargetTest.cpp",
+ ],
+ static_libs: [
+ "android.hardware.gnss.measurement_corrections@1.0",
+ "android.hardware.gnss.visibility_control@1.0",
+ "android.hardware.gnss@1.0",
+ "android.hardware.gnss@1.1",
+ "android.hardware.gnss@2.0",
+ "android.hardware.gnss@2.1",
+ "android.hardware.gnss@common-vts-lib",
+ ],
+ test_suites: ["general-tests", "vts-core"],
+}
diff --git a/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp b/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp
new file mode 100644
index 0000000..e61d885
--- /dev/null
+++ b/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 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 "VtsHalGnssV2_1TargetTest"
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "gnss_hal_test.h"
+
+using android::hardware::gnss::V2_1::IGnss;
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, GnssHalTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGnss::descriptor)),
+ android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.cpp b/gnss/2.1/vts/functional/gnss_hal_test.cpp
new file mode 100644
index 0000000..7cfe0db
--- /dev/null
+++ b/gnss/2.1/vts/functional/gnss_hal_test.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2019 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 "GnssHalTest"
+
+#include <gnss_hal_test.h>
+#include <chrono>
+#include "Utils.h"
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::gnss::common::Utils;
+
+// Implementations for the main test class for GNSS HAL
+void GnssHalTest::SetUp() {
+ gnss_hal_ = IGnss::getService(GetParam());
+ ASSERT_NE(gnss_hal_, nullptr);
+
+ SetUpGnssCallback();
+}
+
+void GnssHalTest::TearDown() {
+ if (gnss_hal_ != nullptr) {
+ gnss_hal_->cleanup();
+ gnss_hal_ = nullptr;
+ }
+
+ // Set to nullptr to destruct the callback event queues and warn of any unprocessed events.
+ gnss_cb_ = nullptr;
+}
+
+void GnssHalTest::SetUpGnssCallback() {
+ gnss_cb_ = new GnssCallback();
+ ASSERT_NE(gnss_cb_, nullptr);
+
+ auto result = gnss_hal_->setCallback_2_1(gnss_cb_);
+ if (!result.isOk()) {
+ ALOGE("result of failed setCallback %s", result.description().c_str());
+ }
+
+ ASSERT_TRUE(result.isOk());
+ ASSERT_TRUE(result);
+
+ /*
+ * All capabilities, name and systemInfo callbacks should trigger
+ */
+ EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC));
+ EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC));
+ EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC));
+
+ EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1);
+ EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1);
+ EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1);
+}
+
+void GnssHalTest::StopAndClearLocations() {
+ const 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 (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) {
+ }
+ gnss_cb_->location_cbq_.reset();
+}
+
+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
+
+ const 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::StartAndCheckFirstLocation() {
+ const auto result = gnss_hal_->start();
+
+ EXPECT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+
+ /*
+ * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
+ * so allow time to demodulate ephemeris over the air.
+ */
+ const int kFirstGnssLocationTimeoutSeconds = 75;
+
+ EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+ kFirstGnssLocationTimeoutSeconds));
+ int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+ EXPECT_EQ(locationCalledCount, 1);
+
+ if (locationCalledCount > 0) {
+ // don't require speed on first fix
+ CheckLocation(gnss_cb_->last_location_, false);
+ return true;
+ }
+ return false;
+}
+
+void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) {
+ const bool check_more_accuracies =
+ (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017);
+
+ Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies);
+}
+
+void GnssHalTest::StartAndCheckLocations(int count) {
+ const int kMinIntervalMsec = 500;
+ const int kLocationTimeoutSubsequentSec = 2;
+ const bool kLowPowerMode = false;
+
+ SetPositionMode(kMinIntervalMsec, kLowPowerMode);
+
+ EXPECT_TRUE(StartAndCheckFirstLocation());
+
+ for (int i = 1; i < count; i++) {
+ EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+ kLocationTimeoutSubsequentSec));
+ int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+ EXPECT_EQ(locationCalledCount, i + 1);
+ // Don't cause confusion by checking details if no location yet
+ if (locationCalledCount > 0) {
+ // Should be more than 1 location by now, but if not, still don't check first fix speed
+ CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1);
+ }
+ }
+}
+
+GnssHalTest::GnssCallback::GnssCallback()
+ : info_cbq_("system_info"),
+ name_cbq_("name"),
+ capabilities_cbq_("capabilities"),
+ location_cbq_("location"),
+ sv_info_list_cbq_("sv_info") {}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
+ const IGnssCallback_1_0::GnssSystemInfo& info) {
+ ALOGI("Info received, year %d", info.yearOfHw);
+ info_cbq_.store(info);
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+ ALOGI("Capabilities received %d", capabilities);
+ capabilities_cbq_.store(capabilities);
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
+ ALOGI("Capabilities (v2.0) received %d", capabilities);
+ capabilities_cbq_.store(capabilities);
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
+ ALOGI("Name received: %s", name.c_str());
+ name_cbq_.store(name);
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) {
+ ALOGI("Location received");
+ GnssLocation_2_0 location_v2_0;
+ location_v2_0.v1_0 = location;
+ return gnssLocationCbImpl(location_v2_0);
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) {
+ ALOGI("Location (v2.0) received");
+ return gnssLocationCbImpl(location);
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) {
+ location_cbq_.store(location);
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) {
+ ALOGI("gnssSvStatusCb");
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb_2_1(
+ const hidl_vec<IGnssCallback_2_1::GnssSvInfo>& svInfoList) {
+ ALOGI("gnssSvStatusCb_2_1. Size = %d", (int)svInfoList.size());
+ sv_info_list_cbq_.store(svInfoList);
+ return Void();
+}
+
+Return<void> GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_1(
+ const IGnssMeasurementCallback_2_1::GnssData& data) {
+ ALOGD("GnssMeasurement v2.1 received. Size = %d", (int)data.measurements.size());
+ measurement_cbq_.store(data);
+ return Void();
+}
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.h b/gnss/2.1/vts/functional/gnss_hal_test.h
new file mode 100644
index 0000000..2e1add0
--- /dev/null
+++ b/gnss/2.1/vts/functional/gnss_hal_test.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef GNSS_HAL_TEST_H_
+#define GNSS_HAL_TEST_H_
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include "GnssCallbackEventQueue.h"
+
+#include <gtest/gtest.h>
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using android::hardware::gnss::common::GnssCallbackEventQueue;
+using android::hardware::gnss::V1_0::GnssLocationFlags;
+using android::hardware::gnss::V2_1::IGnss;
+
+using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
+using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback;
+using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback;
+using IGnssCallback_2_1 = android::hardware::gnss::V2_1::IGnssCallback;
+
+using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback;
+
+using android::sp;
+
+#define TIMEOUT_SEC 2 // for basic commands/responses
+
+// The main test class for GNSS HAL.
+class GnssHalTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override;
+
+ virtual void TearDown() override;
+
+ /* Callback class for data & Event. */
+ class GnssCallback : public IGnssCallback_2_1 {
+ public:
+ IGnssCallback_1_0::GnssSystemInfo last_info_;
+ android::hardware::hidl_string last_name_;
+ uint32_t last_capabilities_;
+ GnssLocation_2_0 last_location_;
+
+ GnssCallbackEventQueue<IGnssCallback_1_0::GnssSystemInfo> info_cbq_;
+ GnssCallbackEventQueue<android::hardware::hidl_string> name_cbq_;
+ GnssCallbackEventQueue<uint32_t> capabilities_cbq_;
+ GnssCallbackEventQueue<GnssLocation_2_0> location_cbq_;
+ GnssCallbackEventQueue<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list_cbq_;
+
+ GnssCallback();
+ virtual ~GnssCallback() = default;
+
+ // Dummy callback handlers
+ Return<void> gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override {
+ return Void();
+ }
+ Return<void> gnssNmeaCb(int64_t /* timestamp */,
+ const android::hardware::hidl_string& /* nmea */) override {
+ return Void();
+ }
+ Return<void> gnssAcquireWakelockCb() override { return Void(); }
+ Return<void> gnssReleaseWakelockCb() override { return Void(); }
+ Return<void> gnssRequestLocationCb(bool /* independentFromGnss */) 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_1_0& location) override;
+ Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+ Return<void> gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override;
+ Return<void> gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override;
+
+ // New in v2.0
+ Return<void> gnssLocationCb_2_0(const GnssLocation_2_0& location) override;
+ Return<void> gnssRequestLocationCb_2_0(bool /* independentFromGnss */,
+ bool /* isUserEmergency */) override {
+ return Void();
+ }
+ Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
+ Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback_2_0::GnssSvInfo>&) override {
+ return Void();
+ }
+
+ // New in v2.1
+ Return<void> gnssSvStatusCb_2_1(
+ const hidl_vec<IGnssCallback_2_1::GnssSvInfo>& svInfoList) override;
+
+ private:
+ Return<void> gnssLocationCbImpl(const GnssLocation_2_0& location);
+ };
+
+ /* Callback class for GnssMeasurement. */
+ class GnssMeasurementCallback : public IGnssMeasurementCallback_2_1 {
+ public:
+ GnssCallbackEventQueue<IGnssMeasurementCallback_2_1::GnssData> measurement_cbq_;
+
+ GnssMeasurementCallback() : measurement_cbq_("measurement"){};
+ virtual ~GnssMeasurementCallback() = default;
+
+ // Methods from V1_0::IGnssMeasurementCallback follow.
+ Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_1_0::GnssData&) override {
+ return Void();
+ }
+
+ // Methods from V1_1::IGnssMeasurementCallback follow.
+ Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_1_1::GnssData&) override {
+ return Void();
+ }
+
+ // Methods from V2_0::IGnssMeasurementCallback follow.
+ Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override {
+ return Void();
+ }
+
+ // Methods from V2_1::IGnssMeasurementCallback follow.
+ Return<void> gnssMeasurementCb_2_1(const IGnssMeasurementCallback_2_1::GnssData&) override;
+ };
+
+ /*
+ * SetUpGnssCallback:
+ * Set GnssCallback and verify the result.
+ */
+ void SetUpGnssCallback();
+
+ /*
+ * StartAndCheckFirstLocation:
+ * Helper function to start location, and check the first one.
+ *
+ * <p> Note this leaves the Location request active, to enable Stop call vs. other call
+ * reordering tests.
+ *
+ * returns true if a location was successfully generated
+ */
+ bool StartAndCheckFirstLocation();
+
+ /*
+ * CheckLocation:
+ * Helper function to vet Location fields
+ *
+ * check_speed: true if speed related fields are also verified.
+ */
+ void CheckLocation(const GnssLocation_2_0& location, const bool check_speed);
+
+ /*
+ * 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.
+ */
+ void StartAndCheckLocations(int count);
+
+ /*
+ * StopAndClearLocations:
+ * Helper function to stop locations, and clear any remaining notifications
+ */
+ void StopAndClearLocations();
+
+ /*
+ * SetPositionMode:
+ * Helper function to set positioning mode and verify output
+ */
+ void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
+
+ sp<IGnss> gnss_hal_; // GNSS HAL to call into
+ sp<GnssCallback> gnss_cb_; // Primary callback interface
+};
+
+#endif // GNSS_HAL_TEST_H_
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
new file mode 100644
index 0000000..ef8249b
--- /dev/null
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 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 <gnss_hal_test.h>
+#include "Utils.h"
+
+#include <gtest/gtest.h>
+
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+
+using android::hardware::gnss::common::Utils;
+
+using IGnssMeasurement_2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
+using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
+using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
+using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
+
+/*
+ * SetupTeardownCreateCleanup:
+ * Requests the gnss HAL then calls cleanup
+ *
+ * Empty test fixture to verify basic Setup & Teardown
+ */
+TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {}
+
+/*
+ * TestGnssMeasurementExtension:
+ * Gets the GnssMeasurementExtension and verifies that it returns an actual extension.
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementExtension) {
+ auto gnssMeasurement_2_1 = gnss_hal_->getExtensionGnssMeasurement_2_1();
+ auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0();
+ auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
+ auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
+ ASSERT_TRUE(gnssMeasurement_2_1.isOk() && gnssMeasurement_2_0.isOk() &&
+ gnssMeasurement_1_1.isOk() && gnssMeasurement_1_0.isOk());
+ sp<IGnssMeasurement_2_1> iGnssMeas_2_1 = gnssMeasurement_2_1;
+ sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
+ sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
+ sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
+ // At least one interface is non-null.
+ int numNonNull = (int)(iGnssMeas_2_1 != nullptr) + (int)(iGnssMeas_2_0 != nullptr) +
+ (int)(iGnssMeas_1_1 != nullptr) + (int)(iGnssMeas_1_0 != nullptr);
+ ASSERT_TRUE(numNonNull >= 1);
+}
+
+/*
+ * TestGnssMeasurementFields:
+ * Sets a GnssMeasurementCallback, waits for a measurement, and verifies
+ * 1. basebandCN0DbHz is valid
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementFields) {
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+
+ auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_1();
+ ASSERT_TRUE(gnssMeasurement.isOk());
+
+ // Skip test if GnssMeasurement v2.1 is not supported
+ sp<IGnssMeasurement_2_1> iGnssMeasurement = gnssMeasurement;
+ if (iGnssMeasurement == nullptr) {
+ return;
+ }
+
+ sp<GnssMeasurementCallback> callback = new GnssMeasurementCallback();
+ auto result = iGnssMeasurement->setCallback_2_1(callback, /* enableFullTracking= */ true);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
+
+ IGnssMeasurementCallback_2_1::GnssData lastMeasurement;
+ ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement,
+ kFirstGnssMeasurementTimeoutSeconds));
+ EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1);
+ ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+ for (auto measurement : lastMeasurement.measurements) {
+ // Verify basebandCn0DbHz is valid.
+ ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0);
+ }
+
+ iGnssMeasurement->close();
+}
+
+/*
+ * TestGnssSvInfoFields:
+ * Gets 1 location and a GnssSvInfo, and verifies
+ * 1. basebandCN0DbHz is valid.
+ */
+TEST_P(GnssHalTest, TestGnssSvInfoFields) {
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckFirstLocation();
+ 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, 0);
+ ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
+ sv_info_list_cbq_size, location_called_count);
+
+ hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list;
+ ASSERT_TRUE(gnss_cb_->sv_info_list_cbq_.retrieve(last_sv_info_list, 1));
+
+ bool nonZeroCn0Found = false;
+ for (auto sv_info : last_sv_info_list) {
+ ASSERT_TRUE(sv_info.basebandCN0DbHz >= 0.0 && sv_info.basebandCN0DbHz <= 65.0);
+ if (sv_info.basebandCN0DbHz > 0.0) {
+ nonZeroCn0Found = true;
+ }
+ }
+ // Assert at least one value is non-zero. Zero is ok in status as it's possibly
+ // reporting a searched but not found satellite.
+ ASSERT_TRUE(nonZeroCn0Found);
+ StopAndClearLocations();
+}
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 4ea97fa..577f6ae 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -28,6 +28,10 @@
],
export_include_dirs: ["include"],
shared_libs: [
+ "libhidlbase",
+ "libutils",
"android.hardware.gnss@1.0",
+ "android.hardware.gnss@2.0",
+ "android.hardware.gnss@2.1",
],
}
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index b9a06e8..6c6d696 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -16,6 +16,7 @@
#include <Constants.h>
#include <Utils.h>
+#include <utils/SystemClock.h>
namespace android {
namespace hardware {
@@ -23,31 +24,188 @@
namespace common {
using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags;
+using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
+using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
+using ElapsedRealtime = V2_0::ElapsedRealtime;
+using ElapsedRealtimeFlags = V2_0::ElapsedRealtimeFlags;
+using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType;
+using IGnssMeasurementCallbackV2_0 = V2_0::IGnssMeasurementCallback;
-GnssLocation Utils::getMockLocation() {
- GnssLocation location = {.gnssLocationFlags = 0xFF,
- .latitudeDegrees = kMockLatitudeDegrees,
- .longitudeDegrees = kMockLongitudeDegrees,
- .altitudeMeters = kMockAltitudeMeters,
- .speedMetersPerSec = kMockSpeedMetersPerSec,
- .bearingDegrees = kMockBearingDegrees,
- .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
- .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
- .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
- .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
- .timestamp = kMockTimestamp};
+GnssDataV2_1 Utils::getMockMeasurementV2_1() {
+ GnssDataV2_0 gnssDataV2_0 = Utils::getMockMeasurementV2_0();
+ V2_1::IGnssMeasurementCallback::GnssMeasurement gnssMeasurementV2_1 = {
+ .v2_0 = gnssDataV2_0.measurements[0],
+ .basebandCN0DbHz = 25.0,
+ };
+ hidl_vec<V2_1::IGnssMeasurementCallback::GnssMeasurement> measurements(1);
+ measurements[0] = gnssMeasurementV2_1;
+ GnssDataV2_1 gnssDataV2_1 = {
+ .measurements = measurements,
+ .clock = gnssDataV2_0.clock,
+ .elapsedRealtime = gnssDataV2_0.elapsedRealtime,
+ };
+ return gnssDataV2_1;
+}
+
+GnssDataV2_0 Utils::getMockMeasurementV2_0() {
+ V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = {
+ .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
+ .svid = (int16_t)6,
+ .constellation = V1_0::GnssConstellationType::UNKNOWN,
+ .timeOffsetNs = 0.0,
+ .receivedSvTimeInNs = 8195997131077,
+ .receivedSvTimeUncertaintyInNs = 15,
+ .cN0DbHz = 30.0,
+ .pseudorangeRateMps = -484.13739013671875,
+ .pseudorangeRateUncertaintyMps = 1.0379999876022339,
+ .accumulatedDeltaRangeState = (uint32_t)V1_0::IGnssMeasurementCallback::
+ GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN,
+ .accumulatedDeltaRangeM = 0.0,
+ .accumulatedDeltaRangeUncertaintyM = 0.0,
+ .carrierFrequencyHz = 1.59975e+09,
+ .multipathIndicator =
+ V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN};
+ V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0};
+ V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {
+ .v1_1 = measurement_1_1,
+ .codeType = "C",
+ .state = GnssMeasurementStateV2_0::STATE_CODE_LOCK |
+ GnssMeasurementStateV2_0::STATE_BIT_SYNC |
+ GnssMeasurementStateV2_0::STATE_SUBFRAME_SYNC |
+ GnssMeasurementStateV2_0::STATE_TOW_DECODED |
+ GnssMeasurementStateV2_0::STATE_GLO_STRING_SYNC |
+ GnssMeasurementStateV2_0::STATE_GLO_TOD_DECODED,
+ .constellation = GnssConstellationTypeV2_0::GLONASS,
+ };
+
+ hidl_vec<IGnssMeasurementCallbackV2_0::GnssMeasurement> measurements(1);
+ measurements[0] = measurement_2_0;
+ V1_0::IGnssMeasurementCallback::GnssClock clock = {.timeNs = 2713545000000,
+ .fullBiasNs = -1226701900521857520,
+ .biasNs = 0.59689998626708984,
+ .biasUncertaintyNs = 47514.989972114563,
+ .driftNsps = -51.757811607455452,
+ .driftUncertaintyNsps = 310.64968328491528,
+ .hwClockDiscontinuityCount = 1};
+
+ ElapsedRealtime timestamp = {
+ .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+ .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+ // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+ // In an actual implementation provide an estimate of the synchronization uncertainty
+ // or don't set the field.
+ .timeUncertaintyNs = 1000000};
+
+ GnssDataV2_0 gnssData = {
+ .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp};
+ return gnssData;
+}
+
+V2_0::GnssLocation Utils::getMockLocationV2_0() {
+ const V2_0::ElapsedRealtime timestamp = {
+ .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+ V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+ .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+ // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+ // In an actual implementation provide an estimate of the synchronization uncertainty
+ // or don't set the field.
+ .timeUncertaintyNs = 1000000};
+
+ V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocationV1_0(),
+ .elapsedRealtime = timestamp};
return location;
}
-GnssSvInfo Utils::getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
- float elevationDegrees, float azimuthDegrees) {
- GnssSvInfo svInfo = {.svid = svid,
- .constellation = type,
- .cN0Dbhz = cN0DbHz,
- .elevationDegrees = elevationDegrees,
- .azimuthDegrees = azimuthDegrees,
- .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
- GnssSvFlags::HAS_ALMANAC_DATA};
+V1_0::GnssLocation Utils::getMockLocationV1_0() {
+ V1_0::GnssLocation location = {
+ .gnssLocationFlags = 0xFF,
+ .latitudeDegrees = kMockLatitudeDegrees,
+ .longitudeDegrees = kMockLongitudeDegrees,
+ .altitudeMeters = kMockAltitudeMeters,
+ .speedMetersPerSec = kMockSpeedMetersPerSec,
+ .bearingDegrees = kMockBearingDegrees,
+ .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
+ .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
+ .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
+ .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
+ .timestamp = kMockTimestamp};
+ return location;
+}
+
+hidl_vec<GnssSvInfoV2_1> Utils::getMockSvInfoListV2_1() {
+ GnssSvInfoV1_0 gnssSvInfoV1_0 =
+ Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS, 32.5, 59.1, 166.5);
+ GnssSvInfoV2_0 gnssSvInfoV2_0 =
+ Utils::getMockSvInfoV2_0(gnssSvInfoV1_0, V2_0::GnssConstellationType::GPS);
+ hidl_vec<GnssSvInfoV2_1> gnssSvInfoList = {
+ Utils::getMockSvInfoV2_1(gnssSvInfoV2_0, 27.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GPS, 27.0,
+ 29.0, 56.5),
+ V2_0::GnssConstellationType::GPS),
+ 22.0),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GPS, 30.5,
+ 71.0, 77.0),
+ V2_0::GnssConstellationType::GPS),
+ 25.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(26, V1_0::GnssConstellationType::GPS, 24.1,
+ 28.0, 253.0),
+ V2_0::GnssConstellationType::GPS),
+ 19.1),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GLONASS,
+ 20.5, 11.5, 116.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 15.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GLONASS,
+ 21.5, 28.5, 186.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 16.5),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(18, V1_0::GnssConstellationType::GLONASS,
+ 28.3, 38.8, 69.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 25.3),
+ getMockSvInfoV2_1(
+ getMockSvInfoV2_0(getMockSvInfoV1_0(10, V1_0::GnssConstellationType::GLONASS,
+ 25.0, 66.0, 247.0),
+ V2_0::GnssConstellationType::GLONASS),
+ 20.0),
+ };
+ return gnssSvInfoList;
+}
+
+GnssSvInfoV2_1 Utils::getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz) {
+ GnssSvInfoV2_1 gnssSvInfoV2_1 = {
+ .v2_0 = gnssSvInfoV2_0,
+ .basebandCN0DbHz = basebandCN0DbHz,
+ };
+ return gnssSvInfoV2_1;
+}
+
+GnssSvInfoV2_0 Utils::getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0,
+ V2_0::GnssConstellationType type) {
+ GnssSvInfoV2_0 gnssSvInfoV2_0 = {
+ .v1_0 = gnssSvInfoV1_0,
+ .constellation = type,
+ };
+ return gnssSvInfoV2_0;
+}
+
+GnssSvInfoV1_0 Utils::getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
+ float cN0DbHz, float elevationDegrees,
+ float azimuthDegrees) {
+ GnssSvInfoV1_0 svInfo = {.svid = svid,
+ .constellation = type,
+ .cN0Dbhz = cN0DbHz,
+ .elevationDegrees = elevationDegrees,
+ .azimuthDegrees = azimuthDegrees,
+ .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
+ GnssSvFlags::HAS_ALMANAC_DATA};
return svInfo;
}
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index 47c8812..e0c61a4 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -18,20 +18,34 @@
#define android_hardware_gnss_common_default_Utils_H_
#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <android/hardware/gnss/2.1/IGnss.h>
-using GnssConstellationType = ::android::hardware::gnss::V1_0::GnssConstellationType;
-using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation;
-using GnssSvInfo = ::android::hardware::gnss::V1_0::IGnssCallback::GnssSvInfo;
+using ::android::hardware::hidl_vec;
namespace android {
namespace hardware {
namespace gnss {
namespace common {
+using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData;
+using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData;
+using GnssSvInfoV1_0 = V1_0::IGnssCallback::GnssSvInfo;
+using GnssSvInfoV2_0 = V2_0::IGnssCallback::GnssSvInfo;
+using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo;
+
struct Utils {
- static GnssLocation getMockLocation();
- static GnssSvInfo getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
- float elevationDegrees, float azimuthDegrees);
+ static GnssDataV2_0 getMockMeasurementV2_0();
+ static GnssDataV2_1 getMockMeasurementV2_1();
+ static V2_0::GnssLocation getMockLocationV2_0();
+ static V1_0::GnssLocation getMockLocationV1_0();
+ static hidl_vec<GnssSvInfoV2_1> getMockSvInfoListV2_1();
+ static GnssSvInfoV2_1 getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz);
+ static GnssSvInfoV2_0 getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0,
+ V2_0::GnssConstellationType type);
+ static GnssSvInfoV1_0 getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
+ float cN0DbHz, float elevationDegrees,
+ float azimuthDegrees);
};
} // namespace common
diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
index 162915e..3dfda19 100644
--- a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
+++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
@@ -79,6 +79,7 @@
void setLayerPerFrameMetadataBlobs(
const hidl_vec<IComposerClient::PerFrameMetadataBlob>& metadata) {
+ // in units of uint32_t's
size_t commandLength = 0;
if (metadata.size() > std::numeric_limits<uint32_t>::max()) {
@@ -86,12 +87,12 @@
return;
}
- // number of blobs
- commandLength += metadata.size();
+ // space for numElements
+ commandLength += 1;
for (auto metadataBlob : metadata) {
- commandLength += sizeof(int32_t); // key of metadata blob
- commandLength += 1; // size information of metadata blob
+ commandLength += 1; // key of metadata blob
+ commandLength += 1; // size information of metadata blob
// metadata content size
size_t metadataSize = metadataBlob.blob.size() / sizeof(uint32_t);
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 0e12283..4409bde 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -527,9 +527,9 @@
HidlBuf key_blob;
KeyCharacteristics key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(key_size, 3)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE),
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE),
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
@@ -579,11 +579,12 @@
for (auto key_size : InvalidKeySizes(Algorithm::RSA)) {
HidlBuf key_blob;
KeyCharacteristics key_characteristics;
- ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(key_size, 3)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE),
- &key_blob, &key_characteristics));
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE),
+ &key_blob, &key_characteristics));
}
}
diff --git a/keymaster/4.0/vts/performance/Android.bp b/keymaster/4.0/vts/performance/Android.bp
new file mode 100644
index 0000000..9434bc9
--- /dev/null
+++ b/keymaster/4.0/vts/performance/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_benchmark {
+ name: "keymaster_benchmark",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "Benchmark.cpp",
+ ],
+ static_libs: [
+ "android.hardware.keymaster@4.0",
+ "libkeymaster4support",
+ "libsoftkeymasterdevice",
+ "libchrome"
+ ],
+}
diff --git a/keymaster/4.0/vts/performance/Benchmark.cpp b/keymaster/4.0/vts/performance/Benchmark.cpp
new file mode 100644
index 0000000..96ef5bf
--- /dev/null
+++ b/keymaster/4.0/vts/performance/Benchmark.cpp
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2019 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 "keymaster_benchmark"
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.0/types.h>
+#include <keymaster/keymaster_configuration.h>
+#include <keymasterV4_0/authorization_set.h>
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <binder/IServiceManager.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <iostream>
+
+#include <log/log.h>
+#include <utils/StrongPointer.h>
+
+#include <benchmark/benchmark.h>
+#include <hidl/Status.h>
+
+#include <base/command_line.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace test {
+
+// libutils:
+using android::OK;
+using android::sp;
+using android::status_t;
+
+// libhidl:
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+
+// IKeymaster:
+using android::IServiceManager;
+using android::hardware::hidl_string;
+using android::hardware::keymaster::V4_0::AuthorizationSet;
+using android::hardware::keymaster::V4_0::AuthorizationSetBuilder;
+using android::hardware::keymaster::V4_0::BlockMode;
+using android::hardware::keymaster::V4_0::ErrorCode;
+using android::hardware::keymaster::V4_0::IKeymasterDevice;
+using android::hardware::keymaster::V4_0::KeyCharacteristics;
+using android::hardware::keymaster::V4_0::SecurityLevel;
+
+// Standard library:
+using std::cerr;
+using std::cout;
+using std::endl;
+using std::optional;
+using std::string;
+using std::unique_ptr;
+using std::vector;
+
+class HidlBuf : public hidl_vec<uint8_t> {
+ typedef hidl_vec<uint8_t> super;
+
+ public:
+ HidlBuf() {}
+ HidlBuf(const super& other) : super(other) {}
+ HidlBuf(super&& other) : super(std::move(other)) {}
+ explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
+
+ HidlBuf& operator=(const super& other) {
+ super::operator=(other);
+ return *this;
+ }
+
+ HidlBuf& operator=(super&& other) {
+ super::operator=(std::move(other));
+ return *this;
+ }
+
+ HidlBuf& operator=(const string& other) {
+ resize(other.size());
+ std::copy(other.begin(), other.end(), begin());
+ return *this;
+ }
+
+ string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
+};
+
+#define SMALL_MESSAGE_SIZE 64
+#define MEDIUM_MESSAGE_SIZE 1024
+#define LARGE_MESSAGE_SIZE 131072
+
+class KeymasterWrapper {
+ private:
+ sp<IKeymasterDevice> keymaster_;
+ SecurityLevel securityLevel_;
+ hidl_string name_;
+ hidl_string author_;
+ HidlBuf key_blob_;
+ KeyCharacteristics key_characteristics_;
+ ErrorCode error_;
+ string key_transform_;
+ string keymaster_name_;
+ uint32_t os_version_;
+ uint32_t os_patch_level_;
+ std::vector<string> message_cache_;
+
+ bool GenerateKey(const AuthorizationSet& authSet) {
+ return (keymaster_
+ ->generateKey(
+ authSet.hidl_data(),
+ [&](ErrorCode hidl_error, const hidl_vec<uint8_t>& hidl_key_blob,
+ const KeyCharacteristics& hidl_key_characteristics) {
+ error_ = hidl_error;
+ key_blob_ = hidl_key_blob;
+ key_characteristics_ = std::move(hidl_key_characteristics);
+ })
+ .isOk() &&
+ error_ == ErrorCode::OK);
+ }
+
+ bool GenerateKey(Algorithm algorithm, int keySize, Digest digest = Digest::NONE,
+ PaddingMode padding = PaddingMode::NONE, optional<BlockMode> blockMode = {}) {
+ AuthorizationSetBuilder authSet = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT)
+ .Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT)
+ .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
+ .Authorization(TAG_PURPOSE, KeyPurpose::VERIFY)
+ .Authorization(TAG_KEY_SIZE, keySize)
+ .Authorization(TAG_ALGORITHM, algorithm)
+ .Digest(digest)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Padding(padding);
+ if (blockMode) {
+ authSet.BlockMode(*blockMode);
+ }
+ if (algorithm == Algorithm::RSA) {
+ authSet.Authorization(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+ }
+ return GenerateKey(authSet);
+ }
+
+ KeymasterWrapper(const sp<IKeymasterDevice> keymaster) {
+ os_version_ = ::keymaster::GetOsVersion();
+ os_patch_level_ = ::keymaster::GetOsPatchlevel();
+ keymaster_ = keymaster;
+ keymaster_->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
+ const hidl_string& author) {
+ securityLevel_ = securityLevel;
+ name_ = name;
+ author_ = author;
+ });
+
+ message_cache_.push_back(string(SMALL_MESSAGE_SIZE, 'x'));
+ message_cache_.push_back(string(MEDIUM_MESSAGE_SIZE, 'x'));
+ message_cache_.push_back(string(LARGE_MESSAGE_SIZE, 'x'));
+ }
+
+ public:
+ static KeymasterWrapper* newInstance(const std::string& keymaster_name) {
+ auto keymaster = IKeymasterDevice::getService(keymaster_name);
+ if (!keymaster) {
+ std::cerr << "Error: unable to find keymaster service named " << keymaster_name
+ << std::endl;
+ return nullptr;
+ }
+ return new KeymasterWrapper(keymaster);
+ }
+
+ bool GenerateKey(string transform, int keySize, bool sign = false) {
+ if (transform == key_transform_) {
+ return true;
+ } else if (key_transform_ != "") {
+ // Deleting old key first
+ if (!DeleteKey()) {
+ return false;
+ }
+ }
+ optional<Algorithm> algorithm = getAlgorithm(transform);
+ if (!algorithm) {
+ cerr << "Error: invalid algorithm " << transform << endl;
+ return false;
+ }
+ key_transform_ = transform;
+ return GenerateKey(*algorithm, keySize, getDigest(transform), getPadding(transform, sign),
+ getBlockMode(transform));
+ }
+
+ bool DeleteKey() {
+ key_blob_ = HidlBuf();
+ key_transform_ = "";
+ return keymaster_->deleteKey(key_blob_).isOk();
+ }
+
+ AuthorizationSet getOperationParams(string transform, bool sign = false) {
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .Padding(getPadding(transform, sign))
+ .Authorization(TAG_MAC_LENGTH, 128)
+ .Digest(getDigest(transform));
+ optional<BlockMode> blockMode = getBlockMode(transform);
+ if (blockMode) {
+ builder.BlockMode(*blockMode);
+ }
+ return std::move(builder);
+ }
+
+ optional<OperationHandle> EncryptBegin(AuthorizationSet& in_params,
+ AuthorizationSet* out_params = new AuthorizationSet) {
+ return Begin(KeyPurpose::ENCRYPT, in_params, out_params);
+ }
+
+ optional<OperationHandle> DecryptBegin(AuthorizationSet& in_params,
+ AuthorizationSet* out_params = new AuthorizationSet) {
+ return Begin(KeyPurpose::DECRYPT, in_params, out_params);
+ }
+
+ optional<OperationHandle> SignBegin(AuthorizationSet& in_params,
+ AuthorizationSet* out_params = new AuthorizationSet) {
+ return Begin(KeyPurpose::SIGN, in_params, out_params);
+ }
+
+ optional<OperationHandle> VerifyBegin(AuthorizationSet& in_params,
+ AuthorizationSet* out_params = new AuthorizationSet) {
+ return Begin(KeyPurpose::VERIFY, in_params, out_params);
+ }
+
+ optional<OperationHandle> Begin(KeyPurpose operation, const AuthorizationSet& in_params,
+ AuthorizationSet* out_params) {
+ OperationHandle op_handle;
+ if (!keymaster_
+ ->begin(operation, key_blob_, in_params.hidl_data(), HardwareAuthToken(),
+ [&](ErrorCode hidl_error,
+ const hidl_vec<KeyParameter>& hidl_out_params,
+ uint64_t hidl_op_handle) {
+ error_ = hidl_error;
+ out_params->push_back(AuthorizationSet(hidl_out_params));
+ op_handle = hidl_op_handle;
+ })
+ .isOk() ||
+ error_ != ErrorCode::OK) {
+ keymaster_->abort(op_handle);
+ return {};
+ }
+ return op_handle;
+ }
+
+ optional<string> ProcessMessage(const OperationHandle& op_handle, const string& message,
+ const AuthorizationSet& in_params,
+ AuthorizationSet* out_params = new AuthorizationSet,
+ const string& signature = "") {
+ static const int HIDL_BUFFER_LIMIT = 1 << 14; // 16KB
+
+ string output;
+ size_t input_consumed = 0;
+ while (message.length() - input_consumed > 0) {
+ if (!keymaster_
+ ->update(op_handle, in_params.hidl_data(),
+ HidlBuf(message.substr(input_consumed, HIDL_BUFFER_LIMIT)),
+ HardwareAuthToken(), VerificationToken(),
+ [&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
+ const hidl_vec<KeyParameter>& hidl_out_params,
+ const HidlBuf& hidl_output) {
+ error_ = hidl_error;
+ out_params->push_back(AuthorizationSet(hidl_out_params));
+ output.append(hidl_output.to_string());
+ input_consumed += hidl_input_consumed;
+ })
+ .isOk() ||
+ error_ != ErrorCode::OK) {
+ keymaster_->abort(op_handle);
+ return {};
+ }
+ }
+
+ if (!keymaster_
+ ->finish(op_handle, in_params.hidl_data(),
+ HidlBuf(message.substr(input_consumed)), HidlBuf(signature),
+ HardwareAuthToken(), VerificationToken(),
+ [&](ErrorCode hidl_error,
+ const hidl_vec<KeyParameter>& hidl_out_params,
+ const HidlBuf& hidl_output) {
+ error_ = hidl_error;
+ out_params->push_back(AuthorizationSet(hidl_out_params));
+ output.append(hidl_output.to_string());
+ })
+ .isOk() ||
+ error_ != ErrorCode::OK) {
+ keymaster_->abort(op_handle);
+ return {};
+ }
+
+ return output;
+ }
+
+ int getError() { return static_cast<int>(error_); }
+
+ const string getHardwareName() { return name_; }
+
+ SecurityLevel getSecurityLevel() { return securityLevel_; }
+
+ const string& GenerateMessage(int size) {
+ for (const string& message : message_cache_) {
+ if (message.size() == size) {
+ return message;
+ }
+ }
+ string message = string(size, 'x');
+ message_cache_.push_back(message);
+ return std::move(message);
+ }
+
+ optional<BlockMode> getBlockMode(string transform) {
+ if (transform.find("/ECB") != string::npos) {
+ return BlockMode::ECB;
+ } else if (transform.find("/CBC") != string::npos) {
+ return BlockMode::CBC;
+ } else if (transform.find("/CTR") != string::npos) {
+ return BlockMode::CTR;
+ } else if (transform.find("/GCM") != string::npos) {
+ return BlockMode::GCM;
+ }
+ return {};
+ }
+
+ PaddingMode getPadding(string transform, bool sign) {
+ if (transform.find("/PKCS7") != string::npos) {
+ return PaddingMode::PKCS7;
+ } else if (transform.find("/PSS") != string::npos) {
+ return PaddingMode::RSA_PSS;
+ } else if (transform.find("/OAEP") != string::npos) {
+ return PaddingMode::RSA_OAEP;
+ } else if (transform.find("/PKCS1") != string::npos) {
+ return sign ? PaddingMode::RSA_PKCS1_1_5_SIGN : PaddingMode::RSA_PKCS1_1_5_ENCRYPT;
+ } else if (sign && transform.find("RSA") != string::npos) {
+ // RSA defaults to PKCS1 for sign
+ return PaddingMode::RSA_PKCS1_1_5_SIGN;
+ }
+ return PaddingMode::NONE;
+ }
+
+ optional<Algorithm> getAlgorithm(string transform) {
+ if (transform.find("AES") != string::npos) {
+ return Algorithm::AES;
+ } else if (transform.find("Hmac") != string::npos) {
+ return Algorithm::HMAC;
+ } else if (transform.find("DESede") != string::npos) {
+ return Algorithm::TRIPLE_DES;
+ } else if (transform.find("RSA") != string::npos) {
+ return Algorithm::RSA;
+ } else if (transform.find("EC") != string::npos) {
+ return Algorithm::EC;
+ }
+ cerr << "Can't find algorithm for " << transform << endl;
+ return {};
+ }
+
+ Digest getDigest(string transform) {
+ if (transform.find("MD5") != string::npos) {
+ return Digest::MD5;
+ } else if (transform.find("SHA1") != string::npos ||
+ transform.find("SHA-1") != string::npos) {
+ return Digest::SHA1;
+ } else if (transform.find("SHA224") != string::npos) {
+ return Digest::SHA_2_224;
+ } else if (transform.find("SHA256") != string::npos) {
+ return Digest::SHA_2_256;
+ } else if (transform.find("SHA384") != string::npos) {
+ return Digest::SHA_2_384;
+ } else if (transform.find("SHA512") != string::npos) {
+ return Digest::SHA_2_512;
+ } else if (transform.find("RSA") != string::npos &&
+ transform.find("OAEP") != string::npos) {
+ return Digest::SHA1;
+ }
+ return Digest::NONE;
+ }
+};
+
+KeymasterWrapper* keymaster;
+
+static void settings(benchmark::internal::Benchmark* benchmark) {
+ benchmark->Unit(benchmark::kMillisecond);
+}
+
+static void addDefaultLabel(benchmark::State& state) {
+ string secLevel;
+ switch (keymaster->getSecurityLevel()) {
+ case SecurityLevel::STRONGBOX:
+ secLevel = "STRONGBOX";
+ break;
+ case SecurityLevel::SOFTWARE:
+ secLevel = "SOFTWARE";
+ break;
+ case SecurityLevel::TRUSTED_ENVIRONMENT:
+ secLevel = "TEE";
+ break;
+ }
+ state.SetLabel("hardware_name:" + keymaster->getHardwareName() + " sec_level:" + secLevel);
+}
+
+// clang-format off
+#define BENCHMARK_KM(func, transform, keySize) \
+ BENCHMARK_CAPTURE(func, transform/keySize, #transform "/" #keySize, keySize)->Apply(settings);
+#define BENCHMARK_KM_MSG(func, transform, keySize, msgSize) \
+ BENCHMARK_CAPTURE(func, transform/keySize/msgSize, #transform "/" #keySize "/" #msgSize, \
+ keySize, msgSize) \
+ ->Apply(settings);
+
+#define BENCHMARK_KM_ALL_MSGS(func, transform, keySize) \
+ BENCHMARK_KM_MSG(func, transform, keySize, SMALL_MESSAGE_SIZE) \
+ BENCHMARK_KM_MSG(func, transform, keySize, MEDIUM_MESSAGE_SIZE) \
+ BENCHMARK_KM_MSG(func, transform, keySize, LARGE_MESSAGE_SIZE)
+
+#define BENCHMARK_KM_CIPHER(transform, keySize, msgSize) \
+ BENCHMARK_KM_MSG(encrypt, transform, keySize, msgSize) \
+ BENCHMARK_KM_MSG(decrypt, transform, keySize, msgSize)
+
+#define BENCHMARK_KM_CIPHER_ALL_MSGS(transform, keySize) \
+ BENCHMARK_KM_ALL_MSGS(encrypt, transform, keySize) \
+ BENCHMARK_KM_ALL_MSGS(decrypt, transform, keySize)
+
+#define BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, keySize) \
+ BENCHMARK_KM_ALL_MSGS(sign, transform, keySize) \
+ BENCHMARK_KM_ALL_MSGS(verify, transform, keySize)
+// clang-format on
+
+/*
+ * ============= KeyGen TESTS ==================
+ */
+static void keygen(benchmark::State& state, string transform, int keySize) {
+ addDefaultLabel(state);
+ for (auto _ : state) {
+ keymaster->GenerateKey(transform, keySize);
+ state.PauseTiming();
+ keymaster->DeleteKey();
+ state.ResumeTiming();
+ }
+}
+
+BENCHMARK_KM(keygen, AES, 128);
+BENCHMARK_KM(keygen, AES, 256);
+
+BENCHMARK_KM(keygen, RSA, 2048);
+BENCHMARK_KM(keygen, RSA, 3072);
+BENCHMARK_KM(keygen, RSA, 4096);
+
+BENCHMARK_KM(keygen, EC, 224);
+BENCHMARK_KM(keygen, EC, 256);
+BENCHMARK_KM(keygen, EC, 384);
+BENCHMARK_KM(keygen, EC, 521);
+
+BENCHMARK_KM(keygen, DESede, 168);
+
+BENCHMARK_KM(keygen, Hmac, 64);
+BENCHMARK_KM(keygen, Hmac, 128);
+BENCHMARK_KM(keygen, Hmac, 256);
+BENCHMARK_KM(keygen, Hmac, 512);
+BENCHMARK_KM(keygen, Hmac, 1024);
+BENCHMARK_KM(keygen, Hmac, 2048);
+BENCHMARK_KM(keygen, Hmac, 4096);
+BENCHMARK_KM(keygen, Hmac, 8192);
+
+/*
+ * ============= SIGNATURE TESTS ==================
+ */
+
+static void sign(benchmark::State& state, string transform, int keySize, int msgSize) {
+ addDefaultLabel(state);
+ if (!keymaster->GenerateKey(transform, keySize, true)) {
+ state.SkipWithError(
+ ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ auto params = keymaster->getOperationParams(transform, true);
+ string message = keymaster->GenerateMessage(msgSize);
+
+ for (auto _ : state) {
+ state.PauseTiming();
+ auto opHandle = keymaster->SignBegin(params);
+ if (!opHandle) {
+ state.SkipWithError(
+ ("Error beginning sign, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ state.ResumeTiming();
+ if (!keymaster->ProcessMessage(*opHandle, message, params)) {
+ state.SkipWithError(("Sign error, " + std::to_string(keymaster->getError())).c_str());
+ break;
+ }
+ }
+}
+
+static void verify(benchmark::State& state, string transform, int keySize, int msgSize) {
+ addDefaultLabel(state);
+ if (!keymaster->GenerateKey(transform, keySize, true)) {
+ state.SkipWithError(
+ ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ AuthorizationSet out_params;
+ AuthorizationSet in_params = keymaster->getOperationParams(transform, true);
+ string message = keymaster->GenerateMessage(msgSize);
+ auto opHandle = keymaster->SignBegin(in_params, &out_params);
+ if (!opHandle) {
+ state.SkipWithError(
+ ("Error beginning sign, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ optional<string> signature =
+ keymaster->ProcessMessage(*opHandle, message, in_params, &out_params);
+ if (!signature) {
+ state.SkipWithError(("Sign error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ in_params.push_back(out_params);
+ for (auto _ : state) {
+ state.PauseTiming();
+ opHandle = keymaster->VerifyBegin(in_params);
+ if (!opHandle) {
+ state.SkipWithError(
+ ("Verify begin error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ state.ResumeTiming();
+ if (!keymaster->ProcessMessage(*opHandle, message, in_params, &out_params, *signature)) {
+ state.SkipWithError(("Verify error, " + std::to_string(keymaster->getError())).c_str());
+ break;
+ }
+ }
+}
+
+// clang-format off
+#define BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(transform) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 64) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 128) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 256) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 512) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 1024) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 2024) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 4096) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 8192)
+
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA1)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA256)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA224)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA256)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA384)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA512)
+
+#define BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(transform) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 224) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 256) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 384) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 521)
+
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(NONEwithECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA1withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA224withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA256withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA384withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA512withECDSA);
+
+#define BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(transform) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 2048) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 3072) \
+ BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 4096)
+
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(MD5withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA1withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA);
+
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(MD5withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA1withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA/PSS);
+// clang-format on
+
+/*
+ * ============= CIPHER TESTS ==================
+ */
+
+static void encrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
+ addDefaultLabel(state);
+ if (!keymaster->GenerateKey(transform, keySize)) {
+ state.SkipWithError(
+ ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ auto params = keymaster->getOperationParams(transform);
+ string message = keymaster->GenerateMessage(msgSize);
+
+ for (auto _ : state) {
+ state.PauseTiming();
+ auto opHandle = keymaster->EncryptBegin(params);
+ if (!opHandle) {
+ state.SkipWithError(
+ ("Encryption begin error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ state.ResumeTiming();
+ if (!keymaster->ProcessMessage(*opHandle, message, params)) {
+ state.SkipWithError(
+ ("Encryption error, " + std::to_string(keymaster->getError())).c_str());
+ break;
+ }
+ }
+}
+
+static void decrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
+ addDefaultLabel(state);
+ if (!keymaster->GenerateKey(transform, keySize)) {
+ state.SkipWithError(
+ ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ AuthorizationSet out_params;
+ AuthorizationSet in_params = keymaster->getOperationParams(transform);
+ string message = keymaster->GenerateMessage(msgSize);
+ auto opHandle = keymaster->EncryptBegin(in_params, &out_params);
+ if (!opHandle) {
+ state.SkipWithError(
+ ("Encryption begin error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ auto encryptedMessage = keymaster->ProcessMessage(*opHandle, message, in_params, &out_params);
+ if (!encryptedMessage) {
+ state.SkipWithError(("Encryption error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ in_params.push_back(out_params);
+ for (auto _ : state) {
+ state.PauseTiming();
+ opHandle = keymaster->DecryptBegin(in_params);
+ if (!opHandle) {
+ state.SkipWithError(
+ ("Decryption begin error, " + std::to_string(keymaster->getError())).c_str());
+ return;
+ }
+ state.ResumeTiming();
+ if (!keymaster->ProcessMessage(*opHandle, *encryptedMessage, in_params)) {
+ state.SkipWithError(
+ ("Decryption error, " + std::to_string(keymaster->getError())).c_str());
+ break;
+ }
+ }
+}
+
+// clang-format off
+// AES
+#define BENCHMARK_KM_CIPHER_ALL_AES_KEYS(transform) \
+ BENCHMARK_KM_CIPHER_ALL_MSGS(transform, 128) \
+ BENCHMARK_KM_CIPHER_ALL_MSGS(transform, 256)
+
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CBC/NoPadding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CBC/PKCS7Padding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CTR/NoPadding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/ECB/NoPadding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/ECB/PKCS7Padding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/GCM/NoPadding);
+
+// Triple DES
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/CBC/NoPadding, 168);
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/CBC/PKCS7Padding, 168);
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/ECB/NoPadding, 168);
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/ECB/PKCS7Padding, 168);
+
+#define BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(transform, msgSize) \
+ BENCHMARK_KM_CIPHER(transform, 2048, msgSize) \
+ BENCHMARK_KM_CIPHER(transform, 3072, msgSize) \
+ BENCHMARK_KM_CIPHER(transform, 4096, msgSize)
+
+BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/NoPadding, SMALL_MESSAGE_SIZE);
+BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/PKCS1Padding, SMALL_MESSAGE_SIZE);
+BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/OAEPPadding, SMALL_MESSAGE_SIZE);
+// clang-format on
+
+} // namespace test
+} // namespace V4_0
+} // namespace keymaster
+} // namespace hardware
+} // namespace android
+
+int main(int argc, char** argv) {
+ ::benchmark::Initialize(&argc, argv);
+ base::CommandLine::Init(argc, argv);
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ auto service_name = command_line->GetSwitchValueASCII("service_name");
+ if (service_name.empty()) {
+ service_name = "default";
+ }
+ android::hardware::keymaster::V4_0::test::keymaster =
+ android::hardware::keymaster::V4_0::test::KeymasterWrapper::newInstance(service_name);
+ if (!android::hardware::keymaster::V4_0::test::keymaster) {
+ return 1;
+ }
+ ::benchmark::RunSpecifiedBenchmarks();
+}
\ No newline at end of file
diff --git a/keymaster/4.0/vts/performance/README b/keymaster/4.0/vts/performance/README
new file mode 100644
index 0000000..57d984a
--- /dev/null
+++ b/keymaster/4.0/vts/performance/README
@@ -0,0 +1,19 @@
+# Keymaster Benchmark
+
+The Keymaster Benchmark is a standalone tool for measuring the performance of keymaster implementations.
+
+## Building
+
+Build:
+`m keymaster_benchmark`
+
+Transfer to device/emulator:
+`adb sync data`
+
+The benchmark executable should will be located at `data/benchmarktest/keymaster_benchmark/keymaster_benchmark` on the device.
+
+## Usage
+
+Keymaster Benchmark is built on [Google microbenchmark library](https://github.com/google/benchmark).
+All of the commandline arguments provided by the microbenchmark library are valid, such as `--benchmark_filter=<regex>` or `benchmark_out_format={json|console|csv}`.
+In addition to the command line arguments provided by microbenchmark, `--service_name=<service_name>` is provided allow specification of the keymaster service name, e.g. specify `--service_name=strongbox` to benchmark strongbox.
diff --git a/radio/1.5/IRadio.hal b/radio/1.5/IRadio.hal
index a3001fd..6d422be 100644
--- a/radio/1.5/IRadio.hal
+++ b/radio/1.5/IRadio.hal
@@ -18,6 +18,8 @@
import @1.4::IRadio;
import @1.5::AccessNetwork;
+import @1.5::NetworkScanRequest;
+import @1.5::RadioAccessSpecifier;
import @1.5::SignalThresholdInfo;
/**
@@ -29,7 +31,6 @@
* setResponseFunctions must work with @1.5::IRadioResponse and @1.5::IRadioIndication.
*/
interface IRadio extends @1.4::IRadio {
-
/**
* Sets the signal strength reporting criteria.
*
@@ -96,4 +97,32 @@
* Response callback is IRadioResponse.canToggleUiccApplicationsEnablementResponse()
*/
oneway canToggleUiccApplicationsEnablement(int32_t serial);
+
+ /**
+ * Specify which bands modem's background scan must act on.
+ * If specifyChannels is true, it only scans bands specified in specifiers.
+ * If specifyChannels is false, it scans all bands.
+ *
+ * For example, CBRS is only on LTE band 48. By specifying this band,
+ * modem saves more power.
+ *
+ * @param serial Serial number of request.
+ * @param specifyChannels whether to scan bands defined in specifiers.
+ * @param specifiers which bands to scan. Only used if specifyChannels is true.
+ *
+ * Response callback is IRadioResponse.setSystemSelectionChannelsResponse()
+ */
+ oneway setSystemSelectionChannels_1_5(int32_t serial, bool specifyChannels,
+ vec<RadioAccessSpecifier> specifiers);
+
+ /**
+ * Starts a network scan
+ *
+ * @param serial Serial number of request.
+ * @param request Defines the radio networks/bands/channels which need to be scanned.
+ *
+ * Same API as @1.4::IRadio.startNetworkScan_1_4, except using
+ * 1.5 version of NetworkScanRequest
+ */
+ oneway startNetworkScan_1_5(int32_t serial, NetworkScanRequest request);
};
diff --git a/radio/1.5/IRadioResponse.hal b/radio/1.5/IRadioResponse.hal
index c136ba6..e7a3852 100644
--- a/radio/1.5/IRadioResponse.hal
+++ b/radio/1.5/IRadioResponse.hal
@@ -69,4 +69,28 @@
* RadioError:INTERNAL_ERR
*/
oneway canToggleUiccApplicationsEnablementResponse(RadioResponseInfo info, bool canToggle);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ */
+ oneway setSystemSelectionChannelsResponse_1_5(RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:DEVICE_IN_USE
+ * RadioError:INTERNAL_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INVALID_ARGUMENTS
+ */
+ oneway startNetworkScanResponse_1_5(RadioResponseInfo info);
};
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index 2441b65..068f56b 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -16,6 +16,13 @@
package android.hardware.radio@1.5;
+import @1.1::EutranBands;
+import @1.1::GeranBands;
+import @1.1::RadioAccessNetworks;
+import @1.1::RadioAccessSpecifier;
+import @1.1::ScanType;
+import @1.1::UtranBands;
+import @1.2::NetworkScanRequest;
import @1.4::AccessNetwork;
/**
@@ -114,3 +121,134 @@
*/
NGRAN = 6,
};
+
+enum RadioAccessNetworks : @1.1::RadioAccessNetworks {
+ NGRAN = 4,
+};
+
+/**
+ * Overwritten from @1.1::RadioAccessSpecifier to add NGRAN and NgranBands
+ */
+struct RadioAccessSpecifier {
+ /**
+ * The type of network to scan.
+ */
+ RadioAccessNetworks radioAccessNetwork;
+
+ /**
+ * The frequency bands to scan.
+ * Maximum length of the vector is 8.
+ */
+ safe_union Bands {
+ /** Valid only if radioAccessNetwork = GERAN. */
+ vec<GeranBands> geranBands;
+ /** Valid only if radioAccessNetwork = UTRAN. */
+ vec<UtranBands> utranBands;
+ /** Valid only if radioAccessNetwork = EUTRAN. */
+ vec<EutranBands> eutranBands;
+ /** Valid only if radioAccessNetwork = NGRAN. */
+ vec<NgranBands> ngranBands;
+ } bands;
+
+ /**
+ * The radio channels to scan as defined in 3GPP TS 25.101 and 36.101.
+ * Maximum length of the vector is 32.
+ */
+ vec<int32_t> channels;
+};
+
+enum NgranBands : int32_t {
+ /** 3GPP TS 28.101-1, Table 5.2-1: FR1 bands */
+ BAND_1 = 1,
+ BAND_2 = 2,
+ BAND_3 = 3,
+ BAND_5 = 5,
+ BAND_7 = 7,
+ BAND_8 = 8,
+ BAND_12 = 12,
+ BAND_20 = 20,
+ BAND_25 = 25,
+ BAND_28 = 28,
+ BAND_34 = 34,
+ BAND_38 = 38,
+ BAND_39 = 39,
+ BAND_40 = 40,
+ BAND_41 = 41,
+ BAND_50 = 50,
+ BAND_51 = 51,
+ BAND_66 = 66,
+ BAND_70 = 70,
+ BAND_71 = 71,
+ BAND_74 = 74,
+ BAND_75 = 75,
+ BAND_76 = 76,
+ BAND_77 = 77,
+ BAND_78 = 78,
+ BAND_79 = 79,
+ BAND_80 = 80,
+ BAND_81 = 81,
+ BAND_82 = 82,
+ BAND_83 = 83,
+ BAND_84 = 84,
+ BAND_86 = 86,
+ /** 3GPP TS 28.101-2, Table 5.2-1: FR2 bands */
+ BAND_257 = 257,
+ BAND_258 = 258,
+ BAND_260 = 260,
+ BAND_261 = 261,
+};
+
+/**
+ * Overwritten from @1.2::NetworkScanRequest to update
+ * RadioAccessSpecifier to 1.5 version
+ */
+struct NetworkScanRequest {
+ ScanType type;
+
+ /**
+ * Time interval in seconds between the completion of one scan and the start of
+ * a subsequent scan.
+ * Implementations may ignore this field unless the 'type' is 'PERIODIC'.
+ * Range: ScanIntervalRange:MIN to ScanIntervalRange:MAX
+ */
+ int32_t interval;
+
+ /**
+ * Networks with bands/channels to scan
+ * Maximum length of the vector is RadioConst:RADIO_ACCESS_SPECIFIER_MAX_SIZE
+ */
+ vec<RadioAccessSpecifier> specifiers;
+
+ /**
+ * Maximum duration of the periodic search (in seconds).
+ * If the search lasts maxSearchTime, it must be terminated.
+ * Range: MaxSearchTimeRange:MIN to MaxSearchTimeRange:MAX
+ */
+ int32_t maxSearchTime;
+
+ /**
+ * Indicates whether the modem must report incremental results of the network scan
+ * to the client.
+ * FALSE – Incremental results must not be reported.
+ * TRUE – Incremental must be reported.
+ */
+ bool incrementalResults;
+
+ /**
+ * Indicates the periodicity with which the modem must report incremental results to
+ * the client (in seconds).
+ * Implementations may ignore this value if the incremental results are not requested.
+ * This value must be less than or equal to maxSearchTime.
+ * Range: IncrementalResultsPeriodicityRange:MIN to IncrementalResultsPeriodicityRange:MAX
+ */
+ int32_t incrementalResultsPeriodicity;
+
+ /**
+ * Describes the List of PLMN ids (MCC-MNC)
+ * If any PLMN of this list is found, search must end at that point and results with all
+ * PLMN found until that point should be sent as response.
+ * If the list is not sent, search to be completed until end and all PLMNs found to be
+ * reported.
+ */
+ vec<string> mccMncs;
+};
diff --git a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
index b72febd..5f11d19 100644
--- a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
+++ b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
@@ -23,4 +23,4 @@
int status = RUN_ALL_TESTS();
LOG(INFO) << "Test result = " << status;
return status;
-}
\ No newline at end of file
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 72e8d5e..4df5b14 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -446,3 +446,422 @@
EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
}
}
+
+/*
+ * Test IRadio.setSystemSelectionChannels_1_5() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, true, {specifier});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+ if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
+ serial = GetRandomSerialNumber();
+ Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, false, {specifier});
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan, rspInfo.error = %s\n", toString(radioRsp_v1_5->rspInfo.error).c_str());
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::SIM_ABSENT}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do
+ // not support the required manual GSM search functionality. This is
+ // tracked in b/112206766. Modems have "GSM" rat scan need to
+ // support scanning requests combined with some parameters.
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid specifier.
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidArgument) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {.type = ScanType::ONE_SHOT,
+ .interval = 60};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid interval (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval1) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 4,
+ .specifiers = {specifier},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidInterval1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid interval (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval2) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 301,
+ .specifiers = {specifier},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidInterval2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid max search time (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime1) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 59,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidMaxSearchTime1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid max search time (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime2) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 3601,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidMaxSearchTime2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid periodicity (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity1) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 600,
+ .incrementalResults = true,
+ .incrementalResultsPeriodicity = 0};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidPeriodicity1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid periodicity (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity2) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 600,
+ .incrementalResults = true,
+ .incrementalResultsPeriodicity = 11};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_InvalidPeriodicity2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_5->rspInfo.error,
+ {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with valid periodicity
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 360,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 10};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_GoodRequest1, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with valid periodicity and plmns
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_GoodRequest2) {
+ serial = GetRandomSerialNumber();
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+ rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+ ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+ .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+ .bands = rasBands,
+ .channels = {1, 2}};
+
+ ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 360,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 10,
+ .mccMncs = {"310410"}};
+
+ Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+ ALOGI("startNetworkScan_GoodRequest2, rspInfo.error = %s\n",
+ toString(radioRsp_v1_5->rspInfo.error).c_str());
+ if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::SIM_ABSENT}));
+ } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+ {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+ RadioError::REQUEST_NOT_SUPPORTED}));
+ }
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index c05359d..01bda69 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -53,7 +53,7 @@
class RadioHidlTest_v1_5;
extern ::android::hardware::radio::V1_4::CardStatus cardStatus;
-/* Callback class for radio respons v1_5 */
+/* Callback class for radio response v1_5 */
class RadioResponse_v1_5 : public ::android::hardware::radio::V1_5::IRadioResponse {
protected:
RadioHidlTest_v1_5& parent_v1_5;
@@ -530,10 +530,17 @@
/* 1.5 Api */
Return<void> setSignalStrengthReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
+
Return<void> enableUiccApplicationsResponse(const RadioResponseInfo& info);
+
Return<void> areUiccApplicationsEnabledResponse(const RadioResponseInfo& info, bool enabled);
+
Return<void> canToggleUiccApplicationsEnablementResponse(const RadioResponseInfo& info,
bool canToggle);
+
+ Return<void> setSystemSelectionChannelsResponse_1_5(const RadioResponseInfo& info);
+
+ Return<void> startNetworkScanResponse_1_5(const RadioResponseInfo& info);
};
/* Callback class for radio indication */
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index 78c03a9..5964c96 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -915,3 +915,16 @@
parent_v1_5.notify(info.serial);
return Void();
}
+
+Return<void> RadioResponse_v1_5::setSystemSelectionChannelsResponse_1_5(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_5.notify(info.serial);
+ return Void();
+}
+
+Return<void> RadioResponse_v1_5::startNetworkScanResponse_1_5(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_v1_5.notify(info.serial);
+ return Void();
+}