Merge "Drop GNSS1.1 and Thermal1.0" into rvc-dev
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 150d641..1519c48 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -455,20 +455,22 @@
sp<IStreamOutCallback> callback = self->mCallback;
if (callback.get() == nullptr) return 0;
ALOGV("asyncCallback() event %d", event);
+ Return<void> result;
switch (event) {
case STREAM_CBK_EVENT_WRITE_READY:
- callback->onWriteReady();
+ result = callback->onWriteReady();
break;
case STREAM_CBK_EVENT_DRAIN_READY:
- callback->onDrainReady();
+ result = callback->onDrainReady();
break;
case STREAM_CBK_EVENT_ERROR:
- callback->onError();
+ result = callback->onError();
break;
default:
ALOGW("asyncCallback() unknown event %d", event);
break;
}
+ ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
return 0;
}
@@ -629,16 +631,18 @@
sp<IStreamOutEventCallback> eventCallback = self->mEventCallback;
if (eventCallback.get() == nullptr) return 0;
ALOGV("%s event %d", __func__, event);
+ Return<void> result;
switch (event) {
case STREAM_EVENT_CBK_TYPE_CODEC_FORMAT_CHANGED: {
hidl_vec<uint8_t> audioMetadata;
audioMetadata.setToExternal((uint8_t*)param, strlen((char*)param));
- eventCallback->onCodecFormatChanged(audioMetadata);
+ result = eventCallback->onCodecFormatChanged(audioMetadata);
} break;
default:
ALOGW("%s unknown event %d", __func__, event);
break;
}
+ ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
return 0;
}
#endif
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index a2f4116..8ef2b43 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -40,7 +40,7 @@
return devs.getDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, {}, AUDIO_FORMAT_DEFAULT);
};
auto primaryMic = getMic(policyConfig.getPrimaryModule()->getDeclaredDevices());
- auto availableMic = getMic(policyConfig.getAvailableInputDevices());
+ auto availableMic = getMic(policyConfig.getInputDevices());
return primaryMic != nullptr && primaryMic->equals(availableMic);
}
diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
index cdea8b6..a8e7c0b 100644
--- a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
+++ b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
@@ -14,22 +14,20 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/automotive/can/1.0/ICanBus.h>
#include <android/hardware/automotive/can/1.0/types.h>
#include <can-vts-utils/can-hal-printers.h>
-#include <can-vts-utils/environment-utils.h>
#include <gmock/gmock.h>
#include <hidl-utils/hidl-utils.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
namespace android::hardware::automotive::can::V1_0::vts {
using hardware::hidl_vec;
-static utils::SimpleHidlEnvironment<ICanBus>* gEnv = nullptr;
-
struct CanMessageListener : public can::V1_0::ICanMessageListener {
virtual Return<void> onReceive(const can::V1_0::CanMessage&) override { return {}; }
};
@@ -38,7 +36,7 @@
virtual Return<void> onError(ErrorEvent, bool) override { return {}; }
};
-class CanBusHalTest : public ::testing::VtsHalHidlTargetTestBase {
+class CanBusHalTest : public ::testing::TestWithParam<std::string> {
protected:
virtual void SetUp() override;
virtual void TearDown() override;
@@ -51,9 +49,8 @@
};
void CanBusHalTest::SetUp() {
- const auto serviceName = gEnv->getServiceName<ICanBus>();
- mCanBus = getService<ICanBus>(serviceName);
- ASSERT_TRUE(mCanBus) << "Couldn't open CAN Bus: " << serviceName;
+ mCanBus = ICanBus::getService(GetParam());
+ ASSERT_TRUE(mCanBus) << "Couldn't open CAN Bus: " << GetParam();
}
void CanBusHalTest::TearDown() {
@@ -75,7 +72,7 @@
return res;
}
-TEST_F(CanBusHalTest, SendNoPayload) {
+TEST_P(CanBusHalTest, SendNoPayload) {
CanMessage msg = {};
msg.id = 0x123;
ASSERT_NE(mCanBus, nullptr);
@@ -83,7 +80,7 @@
ASSERT_EQ(Result::OK, result);
}
-TEST_F(CanBusHalTest, Send8B) {
+TEST_P(CanBusHalTest, Send8B) {
CanMessage msg = {};
msg.id = 0x234;
msg.payload = {1, 2, 3, 4, 5, 6, 7, 8};
@@ -92,7 +89,7 @@
ASSERT_EQ(Result::OK, result);
}
-TEST_F(CanBusHalTest, SendZeroId) {
+TEST_P(CanBusHalTest, SendZeroId) {
CanMessage msg = {};
msg.payload = {1, 2, 3};
@@ -100,7 +97,7 @@
ASSERT_EQ(Result::OK, result);
}
-TEST_F(CanBusHalTest, SendTooLong) {
+TEST_P(CanBusHalTest, SendTooLong) {
CanMessage msg = {};
msg.id = 0x123;
msg.payload = hidl_vec<uint8_t>(102400); // 100kiB
@@ -109,14 +106,14 @@
ASSERT_EQ(Result::PAYLOAD_TOO_LONG, result);
}
-TEST_F(CanBusHalTest, ListenNoFilter) {
+TEST_P(CanBusHalTest, ListenNoFilter) {
const auto [result, closeHandle] = listen({}, new CanMessageListener());
ASSERT_EQ(Result::OK, result);
closeHandle->close().assertOk();
}
-TEST_F(CanBusHalTest, ListenSomeFilter) {
+TEST_P(CanBusHalTest, ListenSomeFilter) {
hidl_vec<CanMessageFilter> filters = {
{0x123, 0x1FF, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE, false},
{0x001, 0x00F, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE, true},
@@ -129,12 +126,12 @@
closeHandle->close().assertOk();
}
-TEST_F(CanBusHalTest, ListenNull) {
+TEST_P(CanBusHalTest, ListenNull) {
const auto [result, closeHandle] = listen({}, nullptr);
ASSERT_EQ(Result::INVALID_ARGUMENTS, result);
}
-TEST_F(CanBusHalTest, DoubleCloseListener) {
+TEST_P(CanBusHalTest, DoubleCloseListener) {
const auto [result, closeHandle] = listen({}, new CanMessageListener());
ASSERT_EQ(Result::OK, result);
@@ -142,12 +139,12 @@
closeHandle->close().assertOk();
}
-TEST_F(CanBusHalTest, DontCloseListener) {
+TEST_P(CanBusHalTest, DontCloseListener) {
const auto [result, closeHandle] = listen({}, new CanMessageListener());
ASSERT_EQ(Result::OK, result);
}
-TEST_F(CanBusHalTest, DoubleCloseErrorListener) {
+TEST_P(CanBusHalTest, DoubleCloseErrorListener) {
auto closeHandle = listenForErrors(new CanErrorListener());
ASSERT_NE(nullptr, closeHandle.get());
@@ -155,7 +152,7 @@
closeHandle->close().assertOk();
}
-TEST_F(CanBusHalTest, DoubleCloseNullErrorListener) {
+TEST_P(CanBusHalTest, DoubleCloseNullErrorListener) {
auto closeHandle = listenForErrors(nullptr);
ASSERT_NE(nullptr, closeHandle.get());
@@ -163,13 +160,11 @@
closeHandle->close().assertOk();
}
-TEST_F(CanBusHalTest, DontCloseErrorListener) {
+TEST_P(CanBusHalTest, DontCloseErrorListener) {
auto closeHandle = listenForErrors(new CanErrorListener());
ASSERT_NE(nullptr, closeHandle.get());
}
-} // namespace android::hardware::automotive::can::V1_0::vts
-
/**
* This test requires that you bring up a valid bus first.
*
@@ -177,19 +172,12 @@
* mma -j && adb root && adb remount && adb sync
*
* Example manual invocation:
- * adb shell /data/nativetest64/VtsHalCanBusV1_0TargetTest/VtsHalCanBusV1_0TargetTest \
- * --hal_service_instance=android.hardware.automotive.can@1.0::ICanBus/<NAME_OF_VALID_BUS>
+ * adb shell canhalctrl up <NAME_OF_VALID_BUS> socketcan can0 125000
+ * adb shell /data/nativetest64/VtsHalCanBusV1_0TargetTest/VtsHalCanBusV1_0TargetTest\
+ * --gtest_filter=*_<NAME_OF_VALID_BUS>
*/
-int main(int argc, char** argv) {
- using android::hardware::automotive::can::V1_0::ICanBus;
- using android::hardware::automotive::can::V1_0::vts::gEnv;
- using android::hardware::automotive::can::V1_0::vts::utils::SimpleHidlEnvironment;
- setenv("TREBLE_TESTING_OVERRIDE", "true", true);
- android::base::SetDefaultTag("CanBusVts");
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
- gEnv = new SimpleHidlEnvironment<ICanBus>;
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- return RUN_ALL_TESTS();
-}
+INSTANTIATE_TEST_SUITE_P( //
+ PerInstance, CanBusHalTest, testing::ValuesIn(getAllHalInstanceNames(ICanBus::descriptor)),
+ PrintInstanceNameToString);
+
+} // namespace android::hardware::automotive::can::V1_0::vts
diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
index 68d555d..9039435 100644
--- a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
+++ b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/automotive/can/1.0/ICanBus.h>
@@ -23,9 +22,11 @@
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <can-vts-utils/bus-enumerator.h>
#include <can-vts-utils/can-hal-printers.h>
-#include <can-vts-utils/environment-utils.h>
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <hidl-utils/hidl-utils.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
#include <utils/Mutex.h>
#include <utils/SystemClock.h>
@@ -39,8 +40,6 @@
using hardware::hidl_vec;
using InterfaceType = ICanController::InterfaceType;
-static utils::SimpleHidlEnvironment<ICanController>* gEnv = nullptr;
-
struct CanMessageListener : public can::V1_0::ICanMessageListener {
DISALLOW_COPY_AND_ASSIGN(CanMessageListener);
@@ -133,12 +132,11 @@
sp<ICanBus> mBus;
};
-class CanBusVirtualHalTest : public ::testing::VtsHalHidlTargetTestBase {
+class CanBusVirtualHalTest : public ::testing::TestWithParam<std::string> {
protected:
virtual void SetUp() override;
-
+ virtual void TearDown() override;
static void SetUpTestCase();
- static void TearDownTestCase();
Bus makeBus();
@@ -147,13 +145,10 @@
private:
unsigned mLastIface = 0;
- static sp<ICanController> mCanController;
- static bool mVirtualSupported;
+ sp<ICanController> mCanController = nullptr;
static bool mTestCaseInitialized;
};
-sp<ICanController> CanBusVirtualHalTest::mCanController = nullptr;
-bool CanBusVirtualHalTest::mVirtualSupported;
hidl_vec<hidl_string> CanBusVirtualHalTest::mBusNames;
bool CanBusVirtualHalTest::mTestCaseInitialized = false;
@@ -170,29 +165,27 @@
}
void CanBusVirtualHalTest::SetUp() {
- if (!mVirtualSupported) GTEST_SKIP();
ASSERT_TRUE(mTestCaseInitialized);
-}
-void CanBusVirtualHalTest::SetUpTestCase() {
- const auto serviceName = gEnv->getServiceName<ICanController>();
- mCanController = getService<ICanController>(serviceName);
- ASSERT_TRUE(mCanController) << "Couldn't open CAN Controller: " << serviceName;
+ mCanController = ICanController::getService(GetParam());
+ ASSERT_TRUE(mCanController) << "Couldn't open CAN Controller: " << GetParam();
hidl_vec<InterfaceType> supported;
mCanController->getSupportedInterfaceTypes(hidl_utils::fill(&supported)).assertOk();
- mVirtualSupported = supported.contains(InterfaceType::VIRTUAL);
+ if (!supported.contains(InterfaceType::VIRTUAL)) GTEST_SKIP();
+}
+void CanBusVirtualHalTest::TearDown() {
+ mCanController.clear();
+}
+
+void CanBusVirtualHalTest::SetUpTestCase() {
mBusNames = utils::getBusNames();
ASSERT_NE(0u, mBusNames.size()) << "No ICanBus HALs defined in device manifest";
mTestCaseInitialized = true;
}
-void CanBusVirtualHalTest::TearDownTestCase() {
- mCanController.clear();
-}
-
Bus CanBusVirtualHalTest::makeBus() {
const auto idx = mLastIface++;
EXPECT_LT(idx, mBusNames.size());
@@ -204,7 +197,7 @@
return Bus(mCanController, config);
}
-TEST_F(CanBusVirtualHalTest, Send) {
+TEST_P(CanBusVirtualHalTest, Send) {
auto bus = makeBus();
CanMessage msg = {};
@@ -214,7 +207,7 @@
bus.send(msg);
}
-TEST_F(CanBusVirtualHalTest, SendAfterClose) {
+TEST_P(CanBusVirtualHalTest, SendAfterClose) {
auto bus = makeBus();
auto zombie = bus.get();
bus.reset();
@@ -223,7 +216,7 @@
ASSERT_EQ(Result::INTERFACE_DOWN, result);
}
-TEST_F(CanBusVirtualHalTest, SendAndRecv) {
+TEST_P(CanBusVirtualHalTest, SendAndRecv) {
if (mBusNames.size() < 2u) GTEST_SKIP() << "Not testable with less than two CAN buses.";
auto bus1 = makeBus();
auto bus2 = makeBus();
@@ -243,7 +236,7 @@
ASSERT_EQ(msg, messages[0]);
}
-TEST_F(CanBusVirtualHalTest, DownOneOfTwo) {
+TEST_P(CanBusVirtualHalTest, DownOneOfTwo) {
if (mBusNames.size() < 2u) GTEST_SKIP() << "Not testable with less than two CAN buses.";
auto bus1 = makeBus();
@@ -254,7 +247,7 @@
bus1.send({});
}
-TEST_F(CanBusVirtualHalTest, FilterPositive) {
+TEST_P(CanBusVirtualHalTest, FilterPositive) {
if (mBusNames.size() < 2u) GTEST_SKIP() << "Not testable with less than two CAN buses.";
auto bus1 = makeBus();
auto bus2 = makeBus();
@@ -418,7 +411,7 @@
ASSERT_EQ(expectedPositive, messagesPositive);
}
-TEST_F(CanBusVirtualHalTest, FilterNegative) {
+TEST_P(CanBusVirtualHalTest, FilterNegative) {
if (mBusNames.size() < 2u) GTEST_SKIP() << "Not testable with less than two CAN buses.";
auto bus1 = makeBus();
auto bus2 = makeBus();
@@ -612,7 +605,7 @@
ASSERT_EQ(expectedNegative, messagesNegative);
}
-TEST_F(CanBusVirtualHalTest, FilterMixed) {
+TEST_P(CanBusVirtualHalTest, FilterMixed) {
if (mBusNames.size() < 2u) GTEST_SKIP() << "Not testable with less than two CAN buses.";
auto bus1 = makeBus();
auto bus2 = makeBus();
@@ -871,22 +864,13 @@
ASSERT_EQ(expectedMixed, messagesMixed);
}
-} // namespace android::hardware::automotive::can::V1_0::vts
-
/**
* Example manual invocation:
- * adb shell /data/nativetest64/VtsHalCanBusVirtualV1_0TargetTest/VtsHalCanBusVirtualV1_0TargetTest\
- * --hal_service_instance=android.hardware.automotive.can@1.0::ICanController/socketcan
+ * adb shell /data/nativetest64/VtsHalCanBusVirtualV1_0TargetTest/VtsHalCanBusVirtualV1_0TargetTest
*/
-int main(int argc, char** argv) {
- using android::hardware::automotive::can::V1_0::ICanController;
- using android::hardware::automotive::can::V1_0::vts::gEnv;
- using android::hardware::automotive::can::V1_0::vts::utils::SimpleHidlEnvironment;
- android::base::SetDefaultTag("CanBusVirtualVts");
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
- gEnv = new SimpleHidlEnvironment<ICanController>;
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- return RUN_ALL_TESTS();
-}
+INSTANTIATE_TEST_SUITE_P( //
+ PerInstance, CanBusVirtualHalTest,
+ testing::ValuesIn(getAllHalInstanceNames(ICanController::descriptor)),
+ PrintInstanceNameToString);
+
+} // namespace android::hardware::automotive::can::V1_0::vts
diff --git a/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp
index 8397215..8ef5758 100644
--- a/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp
+++ b/automotive/can/1.0/vts/functional/VtsHalCanControllerV1_0TargetTest.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/automotive/can/1.0/ICanBus.h>
@@ -23,9 +22,10 @@
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <can-vts-utils/bus-enumerator.h>
#include <can-vts-utils/can-hal-printers.h>
-#include <can-vts-utils/environment-utils.h>
#include <gmock/gmock.h>
#include <hidl-utils/hidl-utils.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
namespace android::hardware::automotive::can::V1_0::vts {
@@ -33,9 +33,7 @@
using InterfaceType = ICanController::InterfaceType;
using IfId = ICanController::BusConfig::InterfaceId;
-static utils::SimpleHidlEnvironment<ICanController>* gEnv = nullptr;
-
-class CanControllerHalTest : public ::testing::VtsHalHidlTargetTestBase {
+class CanControllerHalTest : public ::testing::TestWithParam<std::string> {
protected:
virtual void SetUp() override;
virtual void TearDown() override;
@@ -61,9 +59,8 @@
void CanControllerHalTest::SetUp() {
ASSERT_TRUE(mTestCaseInitialized);
- const auto serviceName = gEnv->getServiceName<ICanController>();
- mCanController = getService<ICanController>(serviceName);
- ASSERT_TRUE(mCanController) << "Couldn't open CAN Controller: " << serviceName;
+ mCanController = ICanController::getService(GetParam());
+ ASSERT_TRUE(mCanController) << "Couldn't open CAN Controller: " << GetParam();
}
void CanControllerHalTest::TearDown() {
@@ -130,12 +127,12 @@
<< " (should be otherwise)";
}
-TEST_F(CanControllerHalTest, SupportsSomething) {
+TEST_P(CanControllerHalTest, SupportsSomething) {
const auto supported = getSupportedInterfaceTypes();
ASSERT_GT(supported.size(), 0u);
}
-TEST_F(CanControllerHalTest, BringUpDown) {
+TEST_P(CanControllerHalTest, BringUpDown) {
const std::string name = mBusNames[0];
assertRegistered(name, false);
@@ -148,12 +145,12 @@
assertRegistered(name, false);
}
-TEST_F(CanControllerHalTest, DownDummy) {
+TEST_P(CanControllerHalTest, DownDummy) {
const auto result = mCanController->downInterface("imnotup");
ASSERT_FALSE(result);
}
-TEST_F(CanControllerHalTest, UpTwice) {
+TEST_P(CanControllerHalTest, UpTwice) {
const std::string name = mBusNames[0];
assertRegistered(name, false);
@@ -169,7 +166,7 @@
assertRegistered(name, false);
}
-TEST_F(CanControllerHalTest, ConfigCompatibility) {
+TEST_P(CanControllerHalTest, ConfigCompatibility) {
// using random-ish addresses, which may not be valid - we can't test the success case
// TODO(b/146214370): move interfaceId constructors to a library
IfId virtualCfg = {};
@@ -231,7 +228,7 @@
}
}
-TEST_F(CanControllerHalTest, FailEmptyName) {
+TEST_P(CanControllerHalTest, FailEmptyName) {
const std::string name = "";
assertRegistered(name, false);
@@ -241,7 +238,7 @@
assertRegistered(name, false);
}
-TEST_F(CanControllerHalTest, FailBadName) {
+TEST_P(CanControllerHalTest, FailBadName) {
// 33 characters (name can be at most 32 characters long)
const std::string name = "ab012345678901234567890123456789c";
@@ -252,7 +249,7 @@
assertRegistered(name, false);
}
-TEST_F(CanControllerHalTest, FailBadVirtualAddress) {
+TEST_P(CanControllerHalTest, FailBadVirtualAddress) {
const std::string name = mBusNames[0];
assertRegistered(name, false);
@@ -262,7 +259,7 @@
assertRegistered(name, false);
}
-TEST_F(CanControllerHalTest, FailBadSocketcanAddress) {
+TEST_P(CanControllerHalTest, FailBadSocketcanAddress) {
const std::string name = mBusNames[0];
assertRegistered(name, false);
@@ -277,7 +274,7 @@
assertRegistered(name, false);
}
-TEST_F(CanControllerHalTest, FailBadSlcanAddress) {
+TEST_P(CanControllerHalTest, FailBadSlcanAddress) {
const std::string name = mBusNames[0];
assertRegistered(name, false);
@@ -292,22 +289,13 @@
assertRegistered(name, false);
}
-} // namespace android::hardware::automotive::can::V1_0::vts
-
/**
* Example manual invocation:
- * adb shell /data/nativetest64/VtsHalCanControllerV1_0TargetTest/VtsHalCanControllerV1_0TargetTest\
- * --hal_service_instance=android.hardware.automotive.can@1.0::ICanController/socketcan
+ * adb shell /data/nativetest64/VtsHalCanControllerV1_0TargetTest/VtsHalCanControllerV1_0TargetTest
*/
-int main(int argc, char** argv) {
- using android::hardware::automotive::can::V1_0::ICanController;
- using android::hardware::automotive::can::V1_0::vts::gEnv;
- using android::hardware::automotive::can::V1_0::vts::utils::SimpleHidlEnvironment;
- android::base::SetDefaultTag("CanControllerVts");
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
- gEnv = new SimpleHidlEnvironment<ICanController>;
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- return RUN_ALL_TESTS();
-}
+INSTANTIATE_TEST_SUITE_P( //
+ PerInstance, CanControllerHalTest,
+ testing::ValuesIn(getAllHalInstanceNames(ICanController::descriptor)),
+ PrintInstanceNameToString);
+
+} // namespace android::hardware::automotive::can::V1_0::vts
diff --git a/automotive/can/1.0/vts/utils/include/can-vts-utils/environment-utils.h b/automotive/can/1.0/vts/utils/include/can-vts-utils/environment-utils.h
deleted file mode 100644
index 3eb9cc1..0000000
--- a/automotive/can/1.0/vts/utils/include/can-vts-utils/environment-utils.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 <VtsHalHidlTargetTestEnvBase.h>
-
-namespace android::hardware::automotive::can::V1_0::vts::utils {
-
-/**
- * Simple test environment.
- *
- * This is a helper class to instantiate a test environment without boilerplate code for cases where
- * there is no need to pass more parameters than just HIDL service instance name.
- *
- * The class implements registerTestServices() by calling registerTestService() on every HIDL
- * interface provided as parameter to this template.
- *
- * Example usage:
- * static utils::SimpleHidlEnvironment<IMyService>* gEnv = nullptr;
- *
- * void CanBusHalTest::SetUp() {
- * const auto serviceName = gEnv->getServiceName<IMyService>();
- * (...)
- * }
- *
- * int main(int argc, char** argv) {
- * gEnv = new SimpleHidlEnvironment<IMyService>;
- * ::testing::AddGlobalTestEnvironment(gEnv);
- * ::testing::InitGoogleTest(&argc, argv);
- * gEnv->init(&argc, argv);
- * return RUN_ALL_TESTS();
- * }
- *
- * \param T... HIDL interface names to register for a test service
- */
-template <typename... T>
-class SimpleHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- virtual void registerTestServices() override {
- // Call registerTestService() for every HIDL interface using this template.
- using expander = int[];
- (void)expander{0, (registerTestService<T>(), 0)...};
- }
-};
-
-} // namespace android::hardware::automotive::can::V1_0::vts::utils
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index 8988bfd..9f7cd3f 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -28,7 +28,7 @@
"android.hardware.automotive.evs@1.0",
"android.hardware.automotive.evs@common-default-lib",
],
- test_suites: ["general-tests"],
+ test_suites: ["vts-core"],
cflags: [
"-O0",
"-g",
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index f7580f0..54862a2 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -17,15 +17,6 @@
#define LOG_TAG "VtsHalEvsTest"
-// Note: We have't got a great way to indicate which target
-// should be tested, so we'll leave the interface served by the
-// default (mock) EVS driver here for easy reference. All
-// actual EVS drivers should serve on the EvsEnumeratorHw name,
-// however, so the code is checked in that way.
-//const static char kEnumeratorName[] = "EvsEnumeratorHw-Mock";
-const static char kEnumeratorName[] = "EvsEnumeratorHw";
-
-
// These values are called out in the EVS design doc (as of Mar 8, 2017)
static const int kMaxStreamStartMilliseconds = 500;
static const int kMinimumFramesPerSecond = 10;
@@ -53,8 +44,9 @@
#include <android/hardware/automotive/evs/1.0/IEvsCameraStream.h>
#include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
using namespace ::android::hardware::automotive::evs::V1_0;
using ::android::hardware::Return;
@@ -64,32 +56,19 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-// Test environment for Evs HIDL HAL.
-class EvsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static EvsHidlEnvironment* Instance() {
- static EvsHidlEnvironment* instance = new EvsHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override { registerTestService<IEvsEnumerator>(); }
-
- private:
- EvsHidlEnvironment() {}
-};
-
// The main test class for EVS
-class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class EvsHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
// Make sure we can connect to the enumerator
- string service_name =
- EvsHidlEnvironment::Instance()->getServiceName<IEvsEnumerator>(kEnumeratorName);
- pEnumerator = getService<IEvsEnumerator>(service_name);
+ std::string service_name = GetParam();
+ pEnumerator = IEvsEnumerator::getService(service_name);
+
ASSERT_NE(pEnumerator.get(), nullptr);
- mIsHwModule = !service_name.compare(kEnumeratorName);
+ // "default" is reserved for EVS manager.
+ constexpr static char kEvsManagerName[] = "default";
+ mIsHwModule = service_name.compare(kEvsManagerName);
}
virtual void TearDown() override {}
@@ -130,7 +109,7 @@
* Opens each camera reported by the enumerator and then explicitly closes it via a
* call to closeCamera. Then repeats the test to ensure all cameras can be reopened.
*/
-TEST_F(EvsHidlTest, CameraOpenClean) {
+TEST_P(EvsHidlTest, CameraOpenClean) {
ALOGI("Starting CameraOpenClean test");
// Get the camera list
@@ -162,7 +141,7 @@
* call. This ensures that the intended "aggressive open" behavior works. This is necessary for
* the system to be tolerant of shutdown/restart race conditions.
*/
-TEST_F(EvsHidlTest, CameraOpenAggressive) {
+TEST_P(EvsHidlTest, CameraOpenAggressive) {
ALOGI("Starting CameraOpenAggressive test");
// Get the camera list
@@ -216,7 +195,7 @@
* DisplayOpen:
* Test both clean shut down and "aggressive open" device stealing behavior.
*/
-TEST_F(EvsHidlTest, DisplayOpen) {
+TEST_P(EvsHidlTest, DisplayOpen) {
ALOGI("Starting DisplayOpen test");
// Request exclusive access to the EVS display, then let it go
@@ -264,7 +243,7 @@
* Validate that display states transition as expected and can be queried from either the display
* object itself or the owning enumerator.
*/
-TEST_F(EvsHidlTest, DisplayStates) {
+TEST_P(EvsHidlTest, DisplayStates) {
ALOGI("Starting DisplayStates test");
// Ensure the display starts in the expected state
@@ -324,7 +303,7 @@
* CameraStreamPerformance:
* Measure and qualify the stream start up time and streaming frame rate of each reported camera
*/
-TEST_F(EvsHidlTest, CameraStreamPerformance) {
+TEST_P(EvsHidlTest, CameraStreamPerformance) {
ALOGI("Starting CameraStreamPerformance test");
// Get the camera list
@@ -387,7 +366,7 @@
* Ensure the camera implementation behaves properly when the client holds onto buffers for more
* than one frame time. The camera must cleanly skip frames until the client is ready again.
*/
-TEST_F(EvsHidlTest, CameraStreamBuffering) {
+TEST_P(EvsHidlTest, CameraStreamBuffering) {
ALOGI("Starting CameraStreamBuffering test");
// Arbitrary constant (should be > 1 and less than crazy)
@@ -456,7 +435,7 @@
* imagery is simply copied to the display buffer and presented on screen. This is the one test
* which a human could observe to see the operation of the system on the physical display.
*/
-TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) {
+TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) {
ALOGI("Starting CameraToDisplayRoundTrip test");
// Get the camera list
@@ -517,7 +496,7 @@
* Verify that each client can start and stop video streams on the same
* underlying camera.
*/
-TEST_F(EvsHidlTest, MultiCameraStream) {
+TEST_P(EvsHidlTest, MultiCameraStream) {
ALOGI("Starting MultiCameraStream test");
if (mIsHwModule) {
@@ -601,11 +580,8 @@
}
-int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- EvsHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance,
+ EvsHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEvsEnumerator::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index cde8048..368a6d4 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -38,16 +38,15 @@
#include <hidl/HidlTransportSupport.h>
#include <hwbinder/ProcessState.h>
-#include <log/log.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
-#include <android/log.h>
#include <android/hardware/automotive/evs/1.1/IEvsCamera.h>
#include <android/hardware/automotive/evs/1.1/IEvsCameraStream.h>
#include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android-base/logging.h>
#include <system/camera_metadata.h>
#include <ui/DisplayConfig.h>
#include <ui/DisplayState.h>
@@ -98,18 +97,19 @@
std::string service_name = GetParam();
pEnumerator = IEvsEnumerator::getService(service_name);
ASSERT_NE(pEnumerator.get(), nullptr);
+ LOG(INFO) << "Test target service: " << service_name;
mIsHwModule = pEnumerator->isHardware();
}
virtual void TearDown() override {
// Attempt to close any active camera
- for (auto &&c : activeCameras) {
- sp<IEvsCamera_1_1> cam = c.promote();
+ for (auto &&cam : activeCameras) {
if (cam != nullptr) {
pEnumerator->closeCamera(cam);
}
}
+ activeCameras.clear();
}
protected:
@@ -120,11 +120,12 @@
// Get the camera list
pEnumerator->getCameraList_1_1(
[this](hidl_vec <CameraDesc> cameraList) {
- ALOGI("Camera list callback received %zu cameras",
- cameraList.size());
+ LOG(INFO) << "Camera list callback received "
+ << cameraList.size()
+ << " cameras";
cameraInfo.reserve(cameraList.size());
for (auto&& cam: cameraList) {
- ALOGI("Found camera %s", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Found camera " << cam.v1.cameraId;
cameraInfo.push_back(cam);
}
}
@@ -137,10 +138,12 @@
// Get the ultrasonics array list
pEnumerator->getUltrasonicsArrayList([this](hidl_vec<UltrasonicsArrayDesc> ultraList) {
- ALOGI("Ultrasonics array list callback received %zu arrays", ultraList.size());
+ LOG(INFO) << "Ultrasonics array list callback received "
+ << ultraList.size()
+ << " arrays";
ultrasonicsArraysInfo.reserve(ultraList.size());
for (auto&& ultraArray : ultraList) {
- ALOGI("Found ultrasonics array %s", ultraArray.ultrasonicsArrayId.c_str());
+ LOG(INFO) << "Found ultrasonics array " << ultraArray.ultrasonicsArrayId;
ultrasonicsArraysInfo.push_back(ultraArray);
}
});
@@ -195,7 +198,7 @@
if (!flag) {
// EVS assumes that the device w/o a valid metadata is a physical
// device.
- ALOGI("%s is not a logical camera device.", id.c_str());
+ LOG(INFO) << id << " is not a logical camera device.";
physicalCameras.emplace(id);
return physicalCameras;
}
@@ -205,7 +208,9 @@
int rc = find_camera_metadata_ro_entry(metadata,
ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
&entry);
- ALOGE_IF(rc, "No physical camera ID is found for a logical camera device");
+ if (rc != 0) {
+ LOG(ERROR) << "No physical camera ID is found for a logical camera device";
+ }
const uint8_t *ids = entry.data.u8;
size_t start = 0;
@@ -219,7 +224,10 @@
}
}
- ALOGI("%s consists of %d physical camera devices.", id.c_str(), (int)physicalCameras.size());
+ LOG(INFO) << id
+ << " consists of "
+ << physicalCameras.size()
+ << " physical camera devices";
return physicalCameras;
}
@@ -228,7 +236,7 @@
std::vector<CameraDesc> cameraInfo; // Empty unless/until loadCameraList() is called
bool mIsHwModule; // boolean to tell current module under testing
// is HW module implementation.
- std::deque<wp<IEvsCamera_1_1>> activeCameras; // A list of active camera handles that are
+ std::deque<sp<IEvsCamera_1_1>> activeCameras; // A list of active camera handles that are
// needed to be cleaned up.
std::vector<UltrasonicsArrayDesc>
ultrasonicsArraysInfo; // Empty unless/until
@@ -247,7 +255,7 @@
* call to closeCamera. Then repeats the test to ensure all cameras can be reopened.
*/
TEST_P(EvsHidlTest, CameraOpenClean) {
- ALOGI("Starting CameraOpenClean test");
+ LOG(INFO) << "Starting CameraOpenClean test";
// Get the camera list
loadCameraList();
@@ -261,15 +269,12 @@
bool isLogicalCam = false;
auto devices = getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
if (mIsHwModule && isLogicalCam) {
- ALOGI("Skip a logical device %s for HW module", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device, " << cam.v1.cameraId << " for HW target.";
continue;
}
for (int pass = 0; pass < 2; pass++) {
- activeCameras.clear();
- sp<IEvsCamera_1_1> pCam =
- IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
- .withDefault(nullptr);
+ sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg);
ASSERT_NE(pCam, nullptr);
for (auto&& devName : devices) {
@@ -286,7 +291,7 @@
// Verify that this camera self-identifies correctly
pCam->getCameraInfo_1_1([&cam](CameraDesc desc) {
- ALOGD("Found camera %s", desc.v1.cameraId.c_str());
+ LOG(DEBUG) << "Found camera " << desc.v1.cameraId;
EXPECT_EQ(cam.v1.cameraId, desc.v1.cameraId);
}
);
@@ -295,15 +300,16 @@
const auto id = 0xFFFFFFFF; // meaningless id
hidl_vec<uint8_t> values;
auto err = pCam->setExtendedInfo_1_1(id, values);
- ASSERT_EQ(EvsResult::INVALID_ARG, err);
+ ASSERT_NE(EvsResult::INVALID_ARG, err);
pCam->getExtendedInfo_1_1(id, [](const auto& result, const auto& data) {
- ASSERT_EQ(EvsResult::INVALID_ARG, result);
+ ASSERT_NE(EvsResult::INVALID_ARG, result);
ASSERT_EQ(0, data.size());
});
// Explicitly close the camera so resources are released right away
pEnumerator->closeCamera(pCam);
+ activeCameras.clear();
}
}
}
@@ -316,7 +322,7 @@
* the system to be tolerant of shutdown/restart race conditions.
*/
TEST_P(EvsHidlTest, CameraOpenAggressive) {
- ALOGI("Starting CameraOpenAggressive test");
+ LOG(INFO) << "Starting CameraOpenAggressive test";
// Get the camera list
loadCameraList();
@@ -330,7 +336,7 @@
bool isLogicalCam = false;
getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
if (mIsHwModule && isLogicalCam) {
- ALOGI("Skip a logical device %s for HW module", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device, " << cam.v1.cameraId << " for HW target.";
continue;
}
@@ -345,7 +351,7 @@
// Verify that this camera self-identifies correctly
pCam->getCameraInfo_1_1([&cam](CameraDesc desc) {
- ALOGD("Found camera %s", desc.v1.cameraId.c_str());
+ LOG(DEBUG) << "Found camera " << desc.v1.cameraId;
EXPECT_EQ(cam.v1.cameraId, desc.v1.cameraId);
}
);
@@ -371,16 +377,18 @@
// Close the superceded camera
pEnumerator->closeCamera(pCam);
+ activeCameras.pop_front();
// Verify that the second camera instance self-identifies correctly
pCam2->getCameraInfo_1_1([&cam](CameraDesc desc) {
- ALOGD("Found camera %s", desc.v1.cameraId.c_str());
+ LOG(DEBUG) << "Found camera " << desc.v1.cameraId;
EXPECT_EQ(cam.v1.cameraId, desc.v1.cameraId);
}
);
// Close the second camera instance
pEnumerator->closeCamera(pCam2);
+ activeCameras.pop_front();
}
// Sleep here to ensure the destructor cleanup has time to run so we don't break follow on tests
@@ -393,7 +401,7 @@
* Measure and qualify the stream start up time and streaming frame rate of each reported camera
*/
TEST_P(EvsHidlTest, CameraStreamPerformance) {
- ALOGI("Starting CameraStreamPerformance test");
+ LOG(INFO) << "Starting CameraStreamPerformance test";
// Get the camera list
loadCameraList();
@@ -407,11 +415,10 @@
bool isLogicalCam = false;
auto devices = getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
if (mIsHwModule && isLogicalCam) {
- ALOGI("Skip a logical device %s", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device " << cam.v1.cameraId;
continue;
}
- activeCameras.clear();
sp<IEvsCamera_1_1> pCam =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
.withDefault(nullptr);
@@ -444,8 +451,10 @@
kMaxStreamStartMilliseconds * devices.size());
printf("%s: Measured time to first frame %0.2f ms\n",
cam.v1.cameraId.c_str(), timeToFirstFrame * kNanoToMilliseconds);
- ALOGI("%s: Measured time to first frame %0.2f ms",
- cam.v1.cameraId.c_str(), timeToFirstFrame * kNanoToMilliseconds);
+ LOG(INFO) << cam.v1.cameraId
+ << ": Measured time to first frame "
+ << std::scientific << timeToFirstFrame * kNanoToMilliseconds
+ << " ms.";
// Check aspect ratio
unsigned width = 0, height = 0;
@@ -468,11 +477,14 @@
nsecs_t runTime = end - firstFrame;
float framesPerSecond = framesReceived / (runTime * kNanoToSeconds);
printf("Measured camera rate %3.2f fps\n", framesPerSecond);
- ALOGI("Measured camera rate %3.2f fps", framesPerSecond);
+ LOG(INFO) << "Measured camera rate "
+ << std::scientific << framesPerSecond
+ << " fps.";
EXPECT_GE(framesPerSecond, kMinimumFramesPerSecond);
// Explicitly release the camera
pEnumerator->closeCamera(pCam);
+ activeCameras.clear();
}
}
@@ -483,7 +495,7 @@
* than one frame time. The camera must cleanly skip frames until the client is ready again.
*/
TEST_P(EvsHidlTest, CameraStreamBuffering) {
- ALOGI("Starting CameraStreamBuffering test");
+ LOG(INFO) << "Starting CameraStreamBuffering test";
// Arbitrary constant (should be > 1 and less than crazy)
static const unsigned int kBuffersToHold = 6;
@@ -500,11 +512,10 @@
bool isLogicalCam = false;
getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
if (mIsHwModule && isLogicalCam) {
- ALOGI("Skip a logical device %s for HW module", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device " << cam.v1.cameraId << " for HW target.";
continue;
}
- activeCameras.clear();
sp<IEvsCamera_1_1> pCam =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
.withDefault(nullptr);
@@ -557,6 +568,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam);
+ activeCameras.clear();
}
}
@@ -568,7 +580,7 @@
* which a human could observe to see the operation of the system on the physical display.
*/
TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) {
- ALOGI("Starting CameraToDisplayRoundTrip test");
+ LOG(INFO) << "Starting CameraToDisplayRoundTrip test";
// Get the camera list
loadCameraList();
@@ -587,14 +599,14 @@
// Request exclusive access to the first EVS display
sp<IEvsDisplay_1_1> pDisplay = pEnumerator->openDisplay_1_1(targetDisplayId);
ASSERT_NE(pDisplay, nullptr);
- ALOGI("Display %d is in use.", targetDisplayId);
+ LOG(INFO) << "Display " << targetDisplayId << " is alreay in use.";
// Get the display descriptor
pDisplay->getDisplayInfo_1_1([](const auto& config, const auto& state) {
android::DisplayConfig* pConfig = (android::DisplayConfig*)config.data();
const auto width = pConfig->resolution.getWidth();
const auto height = pConfig->resolution.getHeight();
- ALOGI(" Resolution: %dx%d", width, height);
+ LOG(INFO) << " Resolution: " << width << "x" << height;
ASSERT_GT(width, 0);
ASSERT_GT(height, 0);
@@ -607,11 +619,10 @@
bool isLogicalCam = false;
getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
if (mIsHwModule && isLogicalCam) {
- ALOGI("Skip a logical device %s for HW module", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device " << cam.v1.cameraId << " for HW target.";
continue;
}
- activeCameras.clear();
sp<IEvsCamera_1_1> pCam =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
.withDefault(nullptr);
@@ -654,6 +665,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam);
+ activeCameras.clear();
}
// Explicitly release the display
@@ -667,7 +679,7 @@
* underlying camera.
*/
TEST_P(EvsHidlTest, MultiCameraStream) {
- ALOGI("Starting MultiCameraStream test");
+ LOG(INFO) << "Starting MultiCameraStream test";
if (mIsHwModule) {
// This test is not for HW module implementation.
@@ -683,7 +695,6 @@
// Test each reported camera
for (auto&& cam: cameraInfo) {
- activeCameras.clear();
// Create two camera clients.
sp<IEvsCamera_1_1> pCam0 =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
@@ -735,7 +746,9 @@
nsecs_t runTime = end - firstFrame;
float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
- ALOGI("Measured camera rate %3.2f fps and %3.2f fps", framesPerSecond0, framesPerSecond1);
+ LOG(INFO) << "Measured camera rate "
+ << std::scientific << framesPerSecond0 << " fps and "
+ << framesPerSecond1 << " fps";
EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
@@ -760,6 +773,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam0);
pEnumerator->closeCamera(pCam1);
+ activeCameras.clear();
// TODO(b/145459970, b/145457727): below sleep() is added to ensure the
// destruction of active camera objects; this may be related with two
@@ -774,7 +788,7 @@
* Verify that a client can adjust a camera parameter.
*/
TEST_P(EvsHidlTest, CameraParameter) {
- ALOGI("Starting CameraParameter test");
+ LOG(INFO) << "Starting CameraParameter test";
// Get the camera list
loadCameraList();
@@ -791,11 +805,10 @@
if (isLogicalCam) {
// TODO(b/145465724): Support camera parameter programming on
// logical devices.
- ALOGI("Skip a logical device %s", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device " << cam.v1.cameraId;
continue;
}
- activeCameras.clear();
// Create a camera client
sp<IEvsCamera_1_1> pCam =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
@@ -908,6 +921,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam);
+ activeCameras.clear();
}
}
@@ -918,7 +932,7 @@
* terminates or releases a role.
*/
TEST_P(EvsHidlTest, CameraMasterRelease) {
- ALOGI("Starting CameraMasterRelease test");
+ LOG(INFO) << "Starting CameraMasterRelease test";
if (mIsHwModule) {
// This test is not for HW module implementation.
@@ -939,11 +953,10 @@
if (isLogicalCam) {
// TODO(b/145465724): Support camera parameter programming on
// logical devices.
- ALOGI("Skip a logical device %s", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device " << cam.v1.cameraId;
continue;
}
- activeCameras.clear();
// Create two camera clients.
sp<IEvsCamera_1_1> pCamMaster =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
@@ -1012,7 +1025,7 @@
EvsEventDesc aTargetEvent;
aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification, true)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
@@ -1057,7 +1070,7 @@
EvsEventDesc aTargetEvent;
aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification, true)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
@@ -1089,6 +1102,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCamMaster);
pEnumerator->closeCamera(pCamNonMaster);
+ activeCameras.clear();
}
}
@@ -1099,7 +1113,7 @@
* camera parameters.
*/
TEST_P(EvsHidlTest, MultiCameraParameter) {
- ALOGI("Starting MultiCameraParameter test");
+ LOG(INFO) << "Starting MultiCameraParameter test";
if (mIsHwModule) {
// This test is not for HW module implementation.
@@ -1120,11 +1134,10 @@
if (isLogicalCam) {
// TODO(b/145465724): Support camera parameter programming on
// logical devices.
- ALOGI("Skip a logical device %s", cam.v1.cameraId.c_str());
+ LOG(INFO) << "Skip a logical device " << cam.v1.cameraId;
continue;
}
- activeCameras.clear();
// Create two camera clients.
sp<IEvsCamera_1_1> pCamMaster =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
@@ -1256,7 +1269,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification0)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1273,7 +1286,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification1)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1374,7 +1387,7 @@
EvsEventDesc aTargetEvent;
aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification0, true)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1466,7 +1479,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification0)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1482,7 +1495,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification1)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1562,6 +1575,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCamMaster);
pEnumerator->closeCamera(pCamNonMaster);
+ activeCameras.clear();
}
}
@@ -1572,7 +1586,7 @@
* a master role from other EVS clients without the display.
*/
TEST_P(EvsHidlTest, HighPriorityCameraClient) {
- ALOGI("Starting HighPriorityCameraClient test");
+ LOG(INFO) << "Starting HighPriorityCameraClient test";
if (mIsHwModule) {
// This test is not for HW module implementation.
@@ -1592,8 +1606,6 @@
// Test each reported camera
for (auto&& cam: cameraInfo) {
- activeCameras.clear();
-
// Create two clients
sp<IEvsCamera_1_1> pCam0 =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
@@ -1687,7 +1699,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(CameraParam::AUTO_FOCUS);
aTargetEvent.payload[1] = 0;
if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1740,7 +1752,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(cam1Cmds[0]);
aTargetEvent.payload[1] = val0;
if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1791,7 +1803,7 @@
EvsEventDesc aTargetEvent;
aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
if (!frameHandler1->waitForEvent(aTargetEvent, aNotification, true)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1833,7 +1845,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(CameraParam::AUTO_FOCUS);
aTargetEvent.payload[1] = 0;
if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1882,7 +1894,7 @@
aTargetEvent.payload[0] = static_cast<uint32_t>(cam0Cmds[0]);
aTargetEvent.payload[1] = val0;
if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
- ALOGW("A timer is expired before a target event is fired.");
+ LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
@@ -1931,6 +1943,8 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam0);
pEnumerator->closeCamera(pCam1);
+ activeCameras.clear();
+
}
// Explicitly release the display
@@ -1945,7 +1959,7 @@
* configurations from EVS and uses one of them to start a video stream.
*/
TEST_P(EvsHidlTest, CameraUseStreamConfigToDisplay) {
- ALOGI("Starting CameraUseStreamConfigToDisplay test");
+ LOG(INFO) << "Starting CameraUseStreamConfigToDisplay test";
// Get the camera list
loadCameraList();
@@ -1956,7 +1970,6 @@
// Test each reported camera
for (auto&& cam: cameraInfo) {
- activeCameras.clear();
// choose a configuration that has a frame rate faster than minReqFps.
Stream targetCfg = {};
const int32_t minReqFps = 15;
@@ -2036,6 +2049,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam);
+ activeCameras.clear();
}
// Explicitly release the display
@@ -2049,7 +2063,7 @@
* underlying camera with same configuration.
*/
TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) {
- ALOGI("Starting MultiCameraStream test");
+ LOG(INFO) << "Starting MultiCameraStream test";
if (mIsHwModule) {
// This test is not for HW module implementation.
@@ -2061,7 +2075,6 @@
// Test each reported camera
for (auto&& cam: cameraInfo) {
- activeCameras.clear();
// choose a configuration that has a frame rate faster than minReqFps.
Stream targetCfg = {};
const int32_t minReqFps = 15;
@@ -2094,9 +2107,8 @@
static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
if (!foundCfg) {
- ALOGI("Device %s does not provide a list of supported stream configurations, skipped",
- cam.v1.cameraId.c_str());
-
+ LOG(INFO) << "Device " << cam.v1.cameraId
+ << " does not provide a list of supported stream configurations, skipped";
continue;
}
@@ -2162,7 +2174,9 @@
nsecs_t runTime = end - firstFrame;
float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
- ALOGI("Measured camera rate %3.2f fps and %3.2f fps", framesPerSecond0, framesPerSecond1);
+ LOG(INFO) << "Measured camera rate "
+ << std::scientific << framesPerSecond0 << " fps and "
+ << framesPerSecond1 << " fps";
EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
@@ -2187,6 +2201,7 @@
// Explicitly release the camera
pEnumerator->closeCamera(pCam0);
pEnumerator->closeCamera(pCam1);
+ activeCameras.clear();
}
}
@@ -2198,7 +2213,7 @@
* identifiers.
*/
TEST_P(EvsHidlTest, LogicalCameraMetadata) {
- ALOGI("Starting LogicalCameraMetadata test");
+ LOG(INFO) << "Starting LogicalCameraMetadata test";
// Get the camera list
loadCameraList();
@@ -2222,7 +2237,7 @@
* can be reopened.
*/
TEST_P(EvsHidlTest, UltrasonicsArrayOpenClean) {
- ALOGI("Starting UltrasonicsArrayOpenClean test");
+ LOG(INFO) << "Starting UltrasonicsArrayOpenClean test";
// Get the ultrasonics array list
loadUltrasonicsArrayList();
@@ -2236,7 +2251,7 @@
// Verify that this ultrasonics array self-identifies correctly
pUltrasonicsArray->getUltrasonicArrayInfo([&ultraInfo](UltrasonicsArrayDesc desc) {
- ALOGD("Found ultrasonics array %s", ultraInfo.ultrasonicsArrayId.c_str());
+ LOG(DEBUG) << "Found ultrasonics array " << ultraInfo.ultrasonicsArrayId;
EXPECT_EQ(ultraInfo.ultrasonicsArrayId, desc.ultrasonicsArrayId);
});
@@ -2249,14 +2264,14 @@
// Starts a stream and verifies all data received is valid.
TEST_P(EvsHidlTest, UltrasonicsVerifyStreamData) {
- ALOGI("Starting UltrasonicsVerifyStreamData");
+ LOG(INFO) << "Starting UltrasonicsVerifyStreamData";
// Get the ultrasonics array list
loadUltrasonicsArrayList();
// For each ultrasonics array.
for (auto&& ultraInfo : ultrasonicsArraysInfo) {
- ALOGD("Testing ultrasonics array: %s", ultraInfo.ultrasonicsArrayId.c_str());
+ LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
sp<IEvsUltrasonicsArray> pUltrasonicsArray =
pEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId);
@@ -2285,14 +2300,14 @@
// Sets frames in flight before and after start of stream and verfies success.
TEST_P(EvsHidlTest, UltrasonicsSetFramesInFlight) {
- ALOGI("Starting UltrasonicsSetFramesInFlight");
+ LOG(INFO) << "Starting UltrasonicsSetFramesInFlight";
// Get the ultrasonics array list
loadUltrasonicsArrayList();
// For each ultrasonics array.
for (auto&& ultraInfo : ultrasonicsArraysInfo) {
- ALOGD("Testing ultrasonics array: %s", ultraInfo.ultrasonicsArrayId.c_str());
+ LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
sp<IEvsUltrasonicsArray> pUltrasonicsArray =
pEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId);
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 8e57901..e529675 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -63,6 +63,8 @@
"impl/vhal_v2_0/CommConn.cpp",
"impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
"impl/vhal_v2_0/EmulatedVehicleHal.cpp",
+ "impl/vhal_v2_0/VehicleHalClient.cpp",
+ "impl/vhal_v2_0/VehicleHalServer.cpp",
"impl/vhal_v2_0/VehicleEmulator.cpp",
"impl/vhal_v2_0/PipeComm.cpp",
"impl/vhal_v2_0/ProtoMessageConverter.cpp",
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h
new file mode 100644
index 0000000..5e4bf27
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android::hardware::automotive::vehicle::V2_0 {
+
+/**
+ * Vehicle HAL talks to the vehicle through a client, instead of accessing
+ * the car bus directly, to give us more flexibility on the implementation.
+ * Android OS do not need direct access to the vehicle, and the communication
+ * channel is also customizable.
+ *
+ * Client lives on the Android (HAL) side to talk to the vehicle
+ */
+class IVehicleClient {
+ public:
+ IVehicleClient() = default;
+
+ IVehicleClient(const IVehicleClient&) = delete;
+
+ IVehicleClient& operator=(const IVehicleClient&) = delete;
+
+ IVehicleClient(IVehicleClient&&) = default;
+
+ virtual ~IVehicleClient() = default;
+
+ // Get configuration of all properties from server
+ virtual std::vector<VehiclePropConfig> getAllPropertyConfig() const = 0;
+
+ // Send the set property request to server
+ // updateStatus indicate if VHal should change the status of the value
+ // it should be false except injecting values for e2e tests
+ virtual StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // Receive a new property value from server
+ // updateStatus is true if and only if the value is
+ // generated by car (ECU/fake generator/injected)
+ virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // Dump method forwarded from HIDL's debug()
+ // If implemented, it must return whether the caller should dump its state.
+ virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
+ return true;
+ }
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
index 00b5afe..2908a55 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
@@ -21,6 +21,9 @@
#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include "VehicleClient.h"
+#include "VehicleServer.h"
+
namespace android {
namespace hardware {
namespace automotive {
@@ -34,85 +37,6 @@
*/
/**
- * Vehicle HAL talks to the vehicle through a client, instead of accessing
- * the car bus directly, to give us more flexibility on the implementation.
- * Android OS do not need direct access to the vehicle, and the communication
- * channel is also customizable.
- *
- * Client lives on the Android (HAL) side to talk to the vehicle
- */
-class IVehicleClient {
- public:
- IVehicleClient() = default;
-
- IVehicleClient(const IVehicleClient&) = delete;
-
- IVehicleClient& operator=(const IVehicleClient&) = delete;
-
- IVehicleClient(IVehicleClient&&) = default;
-
- virtual ~IVehicleClient() = default;
-
- // Get configuration of all properties from server
- virtual std::vector<VehiclePropConfig> getAllPropertyConfig() const = 0;
-
- // Send the set property request to server
- // updateStatus indicate if VHal should change the status of the value
- // it should be false except injecting values for e2e tests
- virtual StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Receive a new property value from server
- // updateStatus is true if and only if the value is
- // generated by car (ECU/fake generator/injected)
- virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Dump method forwarded from HIDL's debug()
- // If implemented, it must return whether the caller should dump its state.
- virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
- return true;
- }
-};
-
-/**
- * Server lives on the vehicle side to talk to Android HAL
- */
-class IVehicleServer {
- public:
- IVehicleServer() = default;
-
- IVehicleServer(const IVehicleServer&) = delete;
-
- IVehicleServer& operator=(const IVehicleServer&) = delete;
-
- IVehicleServer(IVehicleServer&&) = default;
-
- virtual ~IVehicleServer() = default;
-
- // Receive the get property configuration request from HAL.
- // Return a list of all property config
- virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() const = 0;
-
- // Receive the set property request from HAL.
- // Process the setting and return the status code
- // updateStatus indicate if VHal should change the status of the value
- // it should be false except injecting values for e2e tests
- virtual StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Receive a new property value from car (via direct connection to the car bus or the emulator)
- // and forward the value to HAL
- // updateStatus is true if and only if the value is
- // generated by car (ECU/fake generator/injected)
- virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Dump method forwarded from HIDL's debug()
- // If implemented, it must return whether the caller should dump its state.
- virtual bool onDump(const hidl_handle& /* handle */,
- const hidl_vec<hidl_string>& /* options */) {
- return true;
- }
-};
-
-/**
* If Android has direct access to the vehicle, then the client and
* the server may act in passthrough mode to avoid extra IPC
*
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
index 946e74d..f2d3c13 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
@@ -21,6 +21,7 @@
#include <deque>
#include <map>
#include <mutex>
+#include <memory>
#include <android/hardware/automotive/vehicle/2.0/types.h>
@@ -205,7 +206,7 @@
InternalPool(VehiclePropertyType type, size_t vectorSize)
: mPropType(type), mVectorSize(vectorSize) {}
- RecyclableType obtain() {
+ RecyclableType obtain() override {
return ObjectPool<VehiclePropValue>::obtain();
}
protected:
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
new file mode 100644
index 0000000..ba9799a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android::hardware::automotive::vehicle::V2_0 {
+
+/**
+ * Server lives on the vehicle side to talk to Android HAL.
+ * Note that the server may not be run on Android
+ */
+class IVehicleServer {
+ public:
+ IVehicleServer() = default;
+
+ IVehicleServer(const IVehicleServer&) = delete;
+
+ IVehicleServer& operator=(const IVehicleServer&) = delete;
+
+ IVehicleServer(IVehicleServer&&) = default;
+
+ virtual ~IVehicleServer() = default;
+
+ // Receive the get property configuration request from HAL.
+ // Return a list of all property config
+ virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() const = 0;
+
+ // Receive the set property request from HAL.
+ // Process the setting and return the status code
+ // updateStatus indicate if VHal should change the status of the value
+ // it should be false except injecting values for e2e tests
+ virtual StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // Receive a new property value from car (via direct connection to the car bus or the emulator)
+ // and forward the value to HAL
+ // updateStatus is true if and only if the value is
+ // generated by car (ECU/fake generator/injected)
+ virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // TODO (chenhaosjtuacm): fix this since there are no HIDL in non-Android OS
+#ifdef __ANDROID__
+ // Dump method forwarded from HIDL's debug()
+ // If implemented, it must return whether the caller should dump its state.
+ virtual bool onDump(const hidl_handle& /* handle */,
+ const hidl_vec<hidl_string>& /* options */) {
+ return true;
+ }
+#endif // __ANDROID__
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
index f97dfa1..9553415 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
@@ -19,7 +19,9 @@
#include <memory>
+#ifdef __ANDROID__
#include <hidl/HidlSupport.h>
+#endif
#include <android/hardware/automotive/vehicle/2.0/types.h>
@@ -69,6 +71,8 @@
void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
const VehiclePropValue::RawValue& src);
+#ifdef __ANDROID__
+
template<typename T>
void shallowCopyHidlVec(hidl_vec<T>* dest, const hidl_vec<T>& src);
@@ -76,6 +80,8 @@
void shallowCopy(VehiclePropValue* dest, const VehiclePropValue& src);
+#endif // __ANDROID__
+
} // namespace V2_0
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
index 40dd56e..0947c9f 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
@@ -131,7 +131,7 @@
ALOGE("Discarding value for prop 0x%x because it contains "
"data that is not consistent with this pool. "
"Expected type: %d, vector size: %zu",
- o->prop, mPropType, mVectorSize);
+ o->prop, toInt(mPropType), mVectorSize);
delete o;
} else {
ObjectPool<VehiclePropValue>::recycle(o);
diff --git a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
index 24b777c..6087bfa 100644
--- a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
@@ -58,6 +58,8 @@
return false;
}
// update the propertyValue.
+ // The timestamp in propertyStore should only be updated by the server side. It indicates
+ // the time when the event is generated by the server.
valueToUpdate->timestamp = propValue.timestamp;
valueToUpdate->value = propValue.value;
if (updateStatus) {
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
index 5b6816e..c16b29a 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
@@ -52,7 +52,7 @@
case VehiclePropertyType::MIXED:
break; // Valid, but nothing to do.
default:
- ALOGE("createVehiclePropValue: unknown type: %d", type);
+ ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
val.reset(nullptr);
}
return val;
@@ -78,13 +78,6 @@
}
}
-template<typename T>
-inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
- for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
- (*dest)[i] = src[i];
- }
-}
-
void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
const VehiclePropValue::RawValue& src) {
dest->int32Values = src.int32Values;
@@ -94,6 +87,15 @@
dest->stringValue = src.stringValue;
}
+#ifdef __ANDROID__
+
+template<typename T>
+inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
+ for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
+ (*dest)[i] = src[i];
+ }
+}
+
template<typename T>
void shallowCopyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
if (src.size() > 0) {
@@ -123,6 +125,7 @@
shallowCopyHidlStr(&dest->value.stringValue, src.value.stringValue);
}
+#endif // __ANDROID__
//} // namespace utils
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 4b94800..53c9ffb 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -17,9 +17,11 @@
#ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_
#define android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
#include <vhal_v2_0/VehicleUtils.h>
+#include <map>
+
namespace android {
namespace hardware {
namespace automotive {
@@ -1017,7 +1019,6 @@
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
-
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index 7f90914..9c3c95f 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -35,346 +35,16 @@
namespace impl {
-void EmulatedVehicleClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
- if (!mPropCallback) {
- LOG(ERROR) << __func__ << ": PropertyCallBackType is not registered!";
- return;
- }
- return mPropCallback(value, updateStatus);
-}
+class EmulatedPassthroughConnector : public PassthroughConnector {
+ public:
+ bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-void EmulatedVehicleClient::registerPropertyValueCallback(PropertyCallBackType&& callback) {
- if (mPropCallback) {
- LOG(ERROR) << __func__ << ": Cannot register multiple callbacks!";
- return;
- }
- mPropCallback = std::move(callback);
-}
+ private:
+ void dumpUserHal(int fd, std::string indent);
+};
-GeneratorHub* EmulatedVehicleServer::getGenerator() {
- return &mGeneratorHub;
-}
-
-VehiclePropValuePool* EmulatedVehicleServer::getValuePool() const {
- if (!mValuePool) {
- LOG(WARNING) << __func__ << ": Value pool not set!";
- }
- return mValuePool;
-}
-
-void EmulatedVehicleServer::setValuePool(VehiclePropValuePool* valuePool) {
- if (!valuePool) {
- LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
- }
- mValuePool = valuePool;
-}
-
-void EmulatedVehicleServer::onFakeValueGenerated(const VehiclePropValue& value) {
- constexpr bool updateStatus = true;
- LOG(DEBUG) << __func__ << ": " << toString(value);
- auto updatedPropValue = getValuePool()->obtain(value);
- if (updatedPropValue) {
- updatedPropValue->timestamp = value.timestamp;
- updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- }
-}
-
-std::vector<VehiclePropConfig> EmulatedVehicleServer::onGetAllPropertyConfig() const {
- std::vector<VehiclePropConfig> vehiclePropConfigs;
- constexpr size_t numOfVehiclePropConfigs =
- sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
- vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
- for (auto& it : kVehicleProperties) {
- vehiclePropConfigs.emplace_back(it.config);
- }
- return vehiclePropConfigs;
-}
-
-StatusCode EmulatedVehicleServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
- constexpr bool updateStatus = true;
-
- LOG(INFO) << __func__;
- const auto& v = request.value;
- if (!v.int32Values.size()) {
- LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
- return StatusCode::INVALID_ARG;
- }
-
- FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
-
- switch (command) {
- case FakeDataCommand::StartLinear: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
- if (v.int32Values.size() < 2) {
- LOG(ERROR) << __func__ << ": expected property ID in int32Values";
- return StatusCode::INVALID_ARG;
- }
- if (!v.int64Values.size()) {
- LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
- return StatusCode::INVALID_ARG;
- }
- if (v.floatValues.size() < 3) {
- LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
- << v.floatValues.size();
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = v.int32Values[1];
- getGenerator()->registerGenerator(cookie,
- std::make_unique<LinearFakeValueGenerator>(request));
- break;
- }
- case FakeDataCommand::StartJson: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
- if (v.stringValue.empty()) {
- LOG(ERROR) << __func__ << ": path to JSON file is missing";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = std::hash<std::string>()(v.stringValue);
- getGenerator()->registerGenerator(cookie,
- std::make_unique<JsonFakeValueGenerator>(request));
- break;
- }
- case FakeDataCommand::StopLinear: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
- if (v.int32Values.size() < 2) {
- LOG(ERROR) << __func__ << ": expected property ID in int32Values";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = v.int32Values[1];
- getGenerator()->unregisterGenerator(cookie);
- break;
- }
- case FakeDataCommand::StopJson: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
- if (v.stringValue.empty()) {
- LOG(ERROR) << __func__ << ": path to JSON file is missing";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = std::hash<std::string>()(v.stringValue);
- getGenerator()->unregisterGenerator(cookie);
- break;
- }
- case FakeDataCommand::KeyPress: {
- LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
- int32_t keyCode = request.value.int32Values[2];
- int32_t display = request.value.int32Values[3];
- // Send back to HAL
- onPropertyValueFromCar(
- *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
- updateStatus);
- onPropertyValueFromCar(
- *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
- updateStatus);
- break;
- }
- default: {
- LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
- return StatusCode::INVALID_ARG;
- }
- }
- return StatusCode::OK;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createApPowerStateReq(
- VehicleApPowerStateReq state, int32_t param) {
- auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
- req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
- req->areaId = 0;
- req->timestamp = elapsedRealtimeNano();
- req->status = VehiclePropertyStatus::AVAILABLE;
- req->value.int32Values[0] = toInt(state);
- req->value.int32Values[1] = param;
- return req;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createHwInputKeyProp(
- VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
- auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
- keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
- keyEvent->areaId = 0;
- keyEvent->timestamp = elapsedRealtimeNano();
- keyEvent->status = VehiclePropertyStatus::AVAILABLE;
- keyEvent->value.int32Values[0] = toInt(action);
- keyEvent->value.int32Values[1] = keyCode;
- keyEvent->value.int32Values[2] = targetDisplay;
- return keyEvent;
-}
-
-StatusCode EmulatedVehicleServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
- // Some properties need to be treated non-trivially
- switch (value.prop) {
- case kGenerateFakeDataControllingProperty:
- return handleGenerateFakeDataRequest(value);
-
- // set the value from vehicle side, used in end to end test.
- case kSetIntPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
- updatedPropValue->prop = value.value.int32Values[0];
- updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
- case kSetFloatPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
- updatedPropValue->prop = value.value.int32Values[0];
- updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
- case kSetBooleanPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
- updatedPropValue->prop = value.value.int32Values[1];
- updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
-
- case AP_POWER_STATE_REPORT:
- switch (value.value.int32Values[0]) {
- case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
- case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
- // CPMS is in WAIT_FOR_VHAL state, simply move to ON
- // Send back to HAL
- // ALWAYS update status for generated property value
- onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
- true /* updateStatus */);
- break;
- case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
- // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
- // Send back to HAL
- // ALWAYS update status for generated property value
- onPropertyValueFromCar(
- *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
- true /* updateStatus */);
- break;
- case toInt(VehicleApPowerStateReport::ON):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
- // Do nothing
- break;
- default:
- // Unknown state
- break;
- }
- break;
- case INITIAL_USER_INFO:
- return onSetInitialUserInfo(value, updateStatus);
- default:
- break;
- }
-
- // In the real vhal, the value will be sent to Car ECU.
- // We just pretend it is done here and send back to HAL
- auto updatedPropValue = getValuePool()->obtain(value);
- updatedPropValue->timestamp = elapsedRealtimeNano();
-
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
-}
-
-/**
- * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
- * indicating what the initial user should be.
- *
- * During normal circumstances, the emulator will reply right away, passing a response if
- * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
- * to boot).
- *
- * But during development / testing, the behavior can be changed using lshal dump, which must use
- * the areaId to indicate what should happen next.
- *
- * So, the behavior of set(INITIAL_USER_INFO) is:
- *
- * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
- * lshal).
- * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
- * InitialUserInfoResponseAction::DEFAULT
- * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
- * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
- * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
- * this error scenario)
- * - if it's 3, then don't send a property change (so Android can emulate a timeout)
- *
- */
-StatusCode EmulatedVehicleServer::onSetInitialUserInfo(const VehiclePropValue& value,
- bool updateStatus) {
- // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
- // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
- // LOG, it's not worth investigating why...
-
- if (value.value.int32Values.size() == 0) {
- LOG(ERROR) << "set(INITIAL_USER_INFO): no int32values, ignoring it: " << toString(value);
- return StatusCode::INVALID_ARG;
- }
-
- if (value.areaId != 0) {
- LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
- mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
- return StatusCode::OK;
- }
- LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);
-
- int32_t requestId = value.value.int32Values[0];
-
- // Create the update property and set common values
- auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
- updatedValue->prop = INITIAL_USER_INFO;
- updatedValue->timestamp = elapsedRealtimeNano();
-
- if (mInitialUserResponseFromCmd == nullptr) {
- updatedValue->value.int32Values.resize(2);
- updatedValue->value.int32Values[0] = requestId;
- updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
- LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
- << toString(*updatedValue);
- onPropertyValueFromCar(*updatedValue, updateStatus);
- return StatusCode::OK;
- }
-
- // mInitialUserResponseFromCmd is used for just one request
- std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
-
- // TODO(b/138709788): rather than populate the raw values directly, it should use the
- // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
-
- switch (response->areaId) {
- case 1:
- LOG(INFO) << "returning response with right request id";
- *updatedValue = *response;
- updatedValue->areaId = 0;
- updatedValue->value.int32Values[0] = requestId;
- break;
- case 2:
- LOG(INFO) << "returning response with wrong request id";
- *updatedValue = *response;
- updatedValue->areaId = 0;
- updatedValue->value.int32Values[0] = -requestId;
- break;
- case 3:
- LOG(INFO) << "not generating a property change event because of lshal prop: "
- << toString(*response);
- return StatusCode::OK;
- default:
- LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
- return StatusCode::INTERNAL_ERROR;
- }
-
- LOG(INFO) << "updating property to: " << toString(*updatedValue);
- onPropertyValueFromCar(*updatedValue, updateStatus);
- return StatusCode::OK;
-}
-
-bool EmulatedVehicleServer::onDump(const hidl_handle& handle,
- const hidl_vec<hidl_string>& options) {
+bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle,
+ const hidl_vec<hidl_string>& options) {
int fd = handle->data[0];
if (options.size() > 0) {
@@ -401,7 +71,7 @@
return true;
}
-void EmulatedVehicleServer::dumpUserHal(int fd, std::string indent) {
+void EmulatedPassthroughConnector::dumpUserHal(int fd, std::string indent) {
if (mInitialUserResponseFromCmd != nullptr) {
dprintf(fd, "%sInitial User Info: %s\n", indent.c_str(),
toString(*mInitialUserResponseFromCmd).c_str());
@@ -410,7 +80,7 @@
}
}
-EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector() {
+PassthroughConnectorPtr makeEmulatedPassthroughConnector() {
return std::make_unique<EmulatedPassthroughConnector>();
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
index 4850d32..57cbb8b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -18,9 +18,9 @@
#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
#include <vhal_v2_0/VehicleConnector.h>
-#include <vhal_v2_0/VehicleHal.h>
-#include "GeneratorHub.h"
+#include "VehicleHalClient.h"
+#include "VehicleHalServer.h"
namespace android {
namespace hardware {
@@ -30,69 +30,10 @@
namespace impl {
-// Extension of the client/server interfaces for emulated vehicle
+using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
+using PassthroughConnectorPtr = std::unique_ptr<PassthroughConnector>;
-class EmulatedVehicleClient : public IVehicleClient {
- public:
- // Type of callback function for handling the new property values
- using PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;
-
- // Method from IVehicleClient
- void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override;
-
- void registerPropertyValueCallback(PropertyCallBackType&& callback);
-
- private:
- PropertyCallBackType mPropCallback;
-};
-
-class EmulatedVehicleServer : public IVehicleServer {
- public:
- // Methods from IVehicleServer
-
- std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
-
- StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
-
- bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
- // Set the Property Value Pool used in this server
- void setValuePool(VehiclePropValuePool* valuePool);
-
- private:
- GeneratorHub* getGenerator();
-
- VehiclePropValuePool* getValuePool() const;
-
- void onFakeValueGenerated(const VehiclePropValue& value);
-
- StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-
- VehicleHal::VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
-
- VehicleHal::VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action,
- int32_t keyCode, int32_t targetDisplay);
-
- // private data members
-
- GeneratorHub mGeneratorHub{
- std::bind(&EmulatedVehicleServer::onFakeValueGenerated, this, std::placeholders::_1)};
-
- VehiclePropValuePool* mValuePool{nullptr};
-
- // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
- std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
- StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
- void dumpUserHal(int fd, std::string indent);
-};
-
-// Helper functions
-
-using EmulatedPassthroughConnector =
- IPassThroughConnector<EmulatedVehicleClient, EmulatedVehicleServer>;
-using EmulatedPassthroughConnectorPtr = std::unique_ptr<EmulatedPassthroughConnector>;
-
-EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector();
+PassthroughConnectorPtr makeEmulatedPassthroughConnector();
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 692c7f7..84354c1 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -15,8 +15,9 @@
*/
#define LOG_TAG "DefaultVehicleHal_v2_0"
-#include <android/log.h>
#include <android-base/macros.h>
+#include <android/log.h>
+#include <sys/system_properties.h>
#include "EmulatedVehicleHal.h"
#include "JsonFakeValueGenerator.h"
@@ -87,12 +88,11 @@
return sensorStore;
}
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore,
- EmulatedVehicleClient* client)
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
: mPropStore(propStore),
mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
- mRecurrentTimer(
- std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)),
+ mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
+ std::placeholders::_1)),
mVehicleClient(client) {
initStaticConfig();
for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
@@ -127,7 +127,9 @@
*outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
break;
}
-
+ if (v.get()) {
+ v->timestamp = elapsedRealtimeNano();
+ }
return v;
}
@@ -187,6 +189,14 @@
return StatusCode::NOT_AVAILABLE;
}
+ if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
+ // Emulator does not support remote brightness control, b/139959479
+ // do not send it down so that it does not bring unnecessary property change event
+ // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
+ // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
+ return StatusCode::OK;
+ }
+
/**
* After checking all conditions, such as the property is available, a real vhal will
* sent the events to Car ECU to take actions.
@@ -212,6 +222,17 @@
return false;
}
+// determine if it's running inside Android Emulator
+static bool isInEmulator() {
+ char propValue[PROP_VALUE_MAX];
+ bool isEmulator = (__system_property_get("ro.kernel.qemu", propValue) != 0);
+ if (!isEmulator) {
+ isEmulator = (__system_property_get("ro.hardware", propValue) != 0) &&
+ (!strcmp(propValue, "ranchu") || !strcmp(propValue, "goldfish"));
+ }
+ return isEmulator;
+}
+
// Parse supported properties list and generate vector of property values to hold current values.
void EmulatedVehicleHal::onCreate() {
static constexpr bool shouldUpdateStatus = true;
@@ -262,6 +283,8 @@
}
initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
+ mInEmulator = isInEmulator();
+ ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
}
std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties() {
@@ -284,6 +307,7 @@
}
if (v.get()) {
+ v->timestamp = elapsedRealtimeNano();
doHalEvent(std::move(v));
}
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index ebc405e..dc05145 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -46,7 +46,7 @@
class EmulatedVehicleHal : public EmulatedVehicleHalIface {
public:
EmulatedVehicleHal(VehiclePropertyStore* propStore,
- EmulatedVehicleClient* client);
+ VehicleHalClient* client);
~EmulatedVehicleHal() = default;
// Methods from VehicleHal
@@ -85,7 +85,8 @@
VehiclePropertyStore* mPropStore;
std::unordered_set<int32_t> mHvacPowerProps;
RecurrentTimer mRecurrentTimer;
- EmulatedVehicleClient* mVehicleClient;
+ VehicleHalClient* mVehicleClient;
+ bool mInEmulator;
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
index d6ad77d..2dc502b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
@@ -19,6 +19,8 @@
#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <chrono>
+
namespace android {
namespace hardware {
namespace automotive {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
index 7bdc97c..96aaafe 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -46,7 +46,8 @@
if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) {
mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion;
}
- VehiclePropValue event = {.prop = mGenCfg.propId};
+ // TODO: (chenhaosjtuacm) remove "{}" if AGL compiler updated
+ VehiclePropValue event = {.timestamp = {}, .areaId = {}, .prop = mGenCfg.propId};
auto& value = event.value;
switch (getPropType(event.prop)) {
case VehiclePropertyType::INT32:
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
new file mode 100644
index 0000000..25ffc6d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VehicleHalClient.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+void VehicleHalClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
+ if (!mPropCallback) {
+ LOG(ERROR) << __func__ << ": PropertyCallBackType is not registered!";
+ return;
+ }
+ return mPropCallback(value, updateStatus);
+}
+
+void VehicleHalClient::registerPropertyValueCallback(PropertyCallBackType&& callback) {
+ if (mPropCallback) {
+ LOG(ERROR) << __func__ << ": Cannot register multiple callbacks!";
+ return;
+ }
+ mPropCallback = std::move(callback);
+}
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
new file mode 100644
index 0000000..6559e2a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vhal_v2_0/VehicleClient.h>
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+// The common client operations that may be used by both native and
+// virtualized VHAL clients.
+class VehicleHalClient : public IVehicleClient {
+ public:
+ // Type of callback function for handling the new property values
+ using PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;
+
+ // Method from IVehicleClient
+ void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override;
+
+ void registerPropertyValueCallback(PropertyCallBackType&& callback);
+
+ private:
+ PropertyCallBackType mPropCallback;
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
new file mode 100644
index 0000000..a91ca8e
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VehicleHalServer.h"
+
+#include <fstream>
+
+#include <android-base/logging.h>
+#include <utils/SystemClock.h>
+
+#include "DefaultConfig.h"
+#include "JsonFakeValueGenerator.h"
+#include "LinearFakeValueGenerator.h"
+#include "Obd2SensorStore.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+GeneratorHub* VehicleHalServer::getGenerator() {
+ return &mGeneratorHub;
+}
+
+VehiclePropValuePool* VehicleHalServer::getValuePool() const {
+ if (!mValuePool) {
+ LOG(WARNING) << __func__ << ": Value pool not set!";
+ }
+ return mValuePool;
+}
+
+void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
+ if (!valuePool) {
+ LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
+ }
+ mValuePool = valuePool;
+}
+
+void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
+ constexpr bool updateStatus = true;
+ LOG(DEBUG) << __func__ << ": " << toString(value);
+ auto updatedPropValue = getValuePool()->obtain(value);
+ if (updatedPropValue) {
+ updatedPropValue->timestamp = value.timestamp;
+ updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ }
+}
+
+std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
+ std::vector<VehiclePropConfig> vehiclePropConfigs;
+ constexpr size_t numOfVehiclePropConfigs =
+ sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
+ vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
+ for (auto& it : kVehicleProperties) {
+ vehiclePropConfigs.emplace_back(it.config);
+ }
+ return vehiclePropConfigs;
+}
+
+StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
+ constexpr bool updateStatus = true;
+
+ LOG(INFO) << __func__;
+ const auto& v = request.value;
+ if (!v.int32Values.size()) {
+ LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+
+ FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
+
+ switch (command) {
+ case FakeDataCommand::StartLinear: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
+ if (v.int32Values.size() < 2) {
+ LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+ if (!v.int64Values.size()) {
+ LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
+ return StatusCode::INVALID_ARG;
+ }
+ if (v.floatValues.size() < 3) {
+ LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
+ << v.floatValues.size();
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ getGenerator()->registerGenerator(cookie,
+ std::make_unique<LinearFakeValueGenerator>(request));
+ break;
+ }
+ case FakeDataCommand::StartJson: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
+ if (v.stringValue.empty()) {
+ LOG(ERROR) << __func__ << ": path to JSON file is missing";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ getGenerator()->registerGenerator(cookie,
+ std::make_unique<JsonFakeValueGenerator>(request));
+ break;
+ }
+ case FakeDataCommand::StopLinear: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
+ if (v.int32Values.size() < 2) {
+ LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ getGenerator()->unregisterGenerator(cookie);
+ break;
+ }
+ case FakeDataCommand::StopJson: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
+ if (v.stringValue.empty()) {
+ LOG(ERROR) << __func__ << ": path to JSON file is missing";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ getGenerator()->unregisterGenerator(cookie);
+ break;
+ }
+ case FakeDataCommand::KeyPress: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
+ int32_t keyCode = request.value.int32Values[2];
+ int32_t display = request.value.int32Values[3];
+ // Send back to HAL
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
+ updateStatus);
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
+ updateStatus);
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
+ return StatusCode::INVALID_ARG;
+ }
+ }
+ return StatusCode::OK;
+}
+
+VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
+ VehicleApPowerStateReq state, int32_t param) {
+ auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
+ req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+ req->areaId = 0;
+ req->timestamp = elapsedRealtimeNano();
+ req->status = VehiclePropertyStatus::AVAILABLE;
+ req->value.int32Values[0] = toInt(state);
+ req->value.int32Values[1] = param;
+ return req;
+}
+
+VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
+ VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+ auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+ keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+ keyEvent->areaId = 0;
+ keyEvent->timestamp = elapsedRealtimeNano();
+ keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+ keyEvent->value.int32Values[0] = toInt(action);
+ keyEvent->value.int32Values[1] = keyCode;
+ keyEvent->value.int32Values[2] = targetDisplay;
+ return keyEvent;
+}
+
+StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
+ // Some properties need to be treated non-trivially
+ switch (value.prop) {
+ case kGenerateFakeDataControllingProperty:
+ return handleGenerateFakeDataRequest(value);
+
+ // set the value from vehicle side, used in end to end test.
+ case kSetIntPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
+ updatedPropValue->prop = value.value.int32Values[0];
+ updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+ case kSetFloatPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
+ updatedPropValue->prop = value.value.int32Values[0];
+ updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+ case kSetBooleanPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
+ updatedPropValue->prop = value.value.int32Values[1];
+ updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+
+ case AP_POWER_STATE_REPORT:
+ switch (value.value.int32Values[0]) {
+ case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+ case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+ // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+ // Send back to HAL
+ // ALWAYS update status for generated property value
+ onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
+ true /* updateStatus */);
+ break;
+ case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+ // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+ // Send back to HAL
+ // ALWAYS update status for generated property value
+ onPropertyValueFromCar(
+ *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
+ true /* updateStatus */);
+ break;
+ case toInt(VehicleApPowerStateReport::ON):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
+ // Do nothing
+ break;
+ default:
+ // Unknown state
+ break;
+ }
+ break;
+ case INITIAL_USER_INFO:
+ return onSetInitialUserInfo(value, updateStatus);
+ default:
+ break;
+ }
+
+ // In the real vhal, the value will be sent to Car ECU.
+ // We just pretend it is done here and send back to HAL
+ auto updatedPropValue = getValuePool()->obtain(value);
+ updatedPropValue->timestamp = elapsedRealtimeNano();
+
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+}
+
+/**
+ * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
+ * indicating what the initial user should be.
+ *
+ * During normal circumstances, the emulator will reply right away, passing a response if
+ * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
+ * to boot).
+ *
+ * But during development / testing, the behavior can be changed using lshal dump, which must use
+ * the areaId to indicate what should happen next.
+ *
+ * So, the behavior of set(INITIAL_USER_INFO) is:
+ *
+ * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
+ * lshal).
+ * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
+ * InitialUserInfoResponseAction::DEFAULT
+ * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
+ * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
+ * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
+ * this error scenario)
+ * - if it's 3, then don't send a property change (so Android can emulate a timeout)
+ *
+ */
+StatusCode VehicleHalServer::onSetInitialUserInfo(const VehiclePropValue& value,
+ bool updateStatus) {
+ // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
+ // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
+ // LOG, it's not worth investigating why...
+
+ if (value.value.int32Values.size() == 0) {
+ LOG(ERROR) << "set(INITIAL_USER_INFO): no int32values, ignoring it: " << toString(value);
+ return StatusCode::INVALID_ARG;
+ }
+
+ if (value.areaId != 0) {
+ LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
+ mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
+ return StatusCode::OK;
+ }
+ LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);
+
+ int32_t requestId = value.value.int32Values[0];
+
+ // Create the update property and set common values
+ auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
+ updatedValue->prop = INITIAL_USER_INFO;
+ updatedValue->timestamp = elapsedRealtimeNano();
+
+ if (mInitialUserResponseFromCmd == nullptr) {
+ updatedValue->value.int32Values.resize(2);
+ updatedValue->value.int32Values[0] = requestId;
+ updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
+ LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
+ << toString(*updatedValue);
+ onPropertyValueFromCar(*updatedValue, updateStatus);
+ return StatusCode::OK;
+ }
+
+ // mInitialUserResponseFromCmd is used for just one request
+ std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
+
+ // TODO(b/138709788): rather than populate the raw values directly, it should use the
+ // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
+
+ switch (response->areaId) {
+ case 1:
+ LOG(INFO) << "returning response with right request id";
+ *updatedValue = *response;
+ updatedValue->areaId = 0;
+ updatedValue->value.int32Values[0] = requestId;
+ break;
+ case 2:
+ LOG(INFO) << "returning response with wrong request id";
+ *updatedValue = *response;
+ updatedValue->areaId = 0;
+ updatedValue->value.int32Values[0] = -requestId;
+ break;
+ case 3:
+ LOG(INFO) << "not generating a property change event because of lshal prop: "
+ << toString(*response);
+ return StatusCode::OK;
+ default:
+ LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
+ return StatusCode::INTERNAL_ERROR;
+ }
+
+ LOG(INFO) << "updating property to: " << toString(*updatedValue);
+ onPropertyValueFromCar(*updatedValue, updateStatus);
+ return StatusCode::OK;
+}
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
new file mode 100644
index 0000000..b1ae106
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vhal_v2_0/VehicleObjectPool.h>
+#include <vhal_v2_0/VehicleServer.h>
+
+#include "GeneratorHub.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+// This contains the common server operations that will be used by
+// both native and virtualized VHAL server. Notice that in the virtualized
+// scenario, the server may be run on a different OS than Android.
+class VehicleHalServer : public IVehicleServer {
+ public:
+ // Methods from IVehicleServer
+
+ std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
+
+ StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+ // Set the Property Value Pool used in this server
+ void setValuePool(VehiclePropValuePool* valuePool);
+
+ private:
+ using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+
+ GeneratorHub* getGenerator();
+
+ VehiclePropValuePool* getValuePool() const;
+
+ void onFakeValueGenerated(const VehiclePropValue& value);
+
+ StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
+
+ VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
+
+ VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
+ int32_t targetDisplay);
+
+ StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
+
+ // data members
+
+ protected:
+ // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
+ std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
+
+ private:
+ GeneratorHub mGeneratorHub{
+ std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
+
+ VehiclePropValuePool* mValuePool{nullptr};
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/bluetooth/1.1/IBluetoothHci.hal b/bluetooth/1.1/IBluetoothHci.hal
index 0f69c6e..2a520c1 100644
--- a/bluetooth/1.1/IBluetoothHci.hal
+++ b/bluetooth/1.1/IBluetoothHci.hal
@@ -35,8 +35,8 @@
initialize_1_1(@1.1::IBluetoothHciCallbacks callback);
/**
- * Send an ISO data packet (as specified in the Bluetooth Specification
- * V6.0) to the Bluetooth controller.
+ * Send an ISO data packet (as specified in the Bluetooth Core
+ * Specification v5.2) to the Bluetooth controller.
* Packets must be processed in order.
* @param data HCI data packet to be sent
*/
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
new file mode 100644
index 0000000..b2e68df
--- /dev/null
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -0,0 +1,61 @@
+//
+// Copyright (C) 2018 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_defaults {
+ name: "libboot_control_defaults",
+ vendor: true,
+ recovery_available: true,
+ relative_install_path: "hw",
+
+ cflags: [
+ "-D_FILE_OFFSET_BITS=64",
+ "-Werror",
+ "-Wall",
+ "-Wextra",
+ ],
+
+ shared_libs: [
+ "android.hardware.boot@1.1",
+ "libbase",
+ "liblog",
+ ],
+ static_libs: [
+ "libbootloader_message_vendor",
+ "libfstab",
+ ],
+}
+
+cc_library_static {
+ name: "libboot_control",
+ defaults: ["libboot_control_defaults"],
+ export_include_dirs: ["include"],
+
+ srcs: ["libboot_control.cpp"],
+}
+
+cc_library_shared {
+ name: "bootctrl.default",
+ defaults: ["libboot_control_defaults"],
+
+ srcs: ["legacy_boot_control.cpp"],
+
+ static_libs: [
+ "libboot_control",
+ ],
+ shared_libs: [
+ "libhardware",
+ ],
+}
diff --git a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
new file mode 100644
index 0000000..5468658
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
@@ -0,0 +1,89 @@
+//
+// 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 <string>
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+
+namespace android {
+namespace bootable {
+
+// Helper library to implement the IBootControl HAL using the misc partition.
+class BootControl {
+ using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;
+
+ public:
+ bool Init();
+ unsigned int GetNumberSlots();
+ unsigned int GetCurrentSlot();
+ bool MarkBootSuccessful();
+ bool SetActiveBootSlot(unsigned int slot);
+ bool SetSlotAsUnbootable(unsigned int slot);
+ bool SetSlotBootable(unsigned int slot);
+ bool IsSlotBootable(unsigned int slot);
+ const char* GetSuffix(unsigned int slot);
+ bool IsSlotMarkedSuccessful(unsigned int slot);
+ bool SetSnapshotMergeStatus(MergeStatus status);
+ MergeStatus GetSnapshotMergeStatus();
+
+ bool IsValidSlot(unsigned int slot);
+
+ const std::string& misc_device() const {
+ return misc_device_;
+ }
+
+ private:
+ // Whether this object was initialized with data from the bootloader message
+ // that doesn't change until next reboot.
+ bool initialized_ = false;
+
+ // The path to the misc_device as reported in the fstab.
+ std::string misc_device_;
+
+ // The number of slots present on the device.
+ unsigned int num_slots_ = 0;
+
+ // The slot where we are running from.
+ unsigned int current_slot_ = 0;
+};
+
+// Helper functions to write the Virtual A/B merge status message. These are
+// separate because BootControl uses bootloader_control_ab in vendor space,
+// whereas the Virtual A/B merge status is in system space. A HAL might not
+// use bootloader_control_ab, but may want to use the AOSP method of maintaining
+// the merge status.
+
+// If the Virtual A/B message has not yet been initialized, then initialize it.
+// This should be called when the BootControl HAL first loads.
+//
+// If the Virtual A/B message in misc was already initialized, true is returned.
+// If initialization was attempted, but failed, false is returned, and the HAL
+// should fail to load.
+bool InitMiscVirtualAbMessageIfNeeded();
+
+// Save the current merge status as well as the current slot.
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus status);
+
+// Return the current merge status. If the saved status is SNAPSHOTTED but the
+// slot hasn't changed, the status returned will be NONE.
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus* status);
+
+} // namespace bootable
+} // namespace android
diff --git a/boot/1.1/default/boot_control/include/private/boot_control_definition.h b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
new file mode 100644
index 0000000..8f02111
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * The A/B-specific bootloader message structure (4-KiB).
+ *
+ * We separate A/B boot control metadata from the regular bootloader
+ * message struct and keep it here. Everything that's A/B-specific
+ * stays after struct bootloader_message, which belongs to the vendor
+ * space of /misc partition. Also, the A/B-specific contents should be
+ * managed by the A/B-bootloader or boot control HAL.
+ *
+ * The slot_suffix field is used for A/B implementations where the
+ * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
+ * commandline parameter. This is used by fs_mgr to mount /system and
+ * other partitions with the slotselect flag set in fstab. A/B
+ * implementations are free to use all 32 bytes and may store private
+ * data past the first NUL-byte in this field. It is encouraged, but
+ * not mandatory, to use 'struct bootloader_control' described below.
+ *
+ * The update_channel field is used to store the Omaha update channel
+ * if update_engine is compiled with Omaha support.
+ */
+struct bootloader_message_ab {
+ struct bootloader_message message;
+ char slot_suffix[32];
+ char update_channel[128];
+
+ // Round up the entire struct to 4096-byte.
+ char reserved[1888];
+};
+
+/**
+ * Be cautious about the struct size change, in case we put anything post
+ * bootloader_message_ab struct (b/29159185).
+ */
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_message_ab) == 4096,
+ "struct bootloader_message_ab size changes");
+#endif
+
+#define BOOT_CTRL_MAGIC 0x42414342 /* Bootloader Control AB */
+#define BOOT_CTRL_VERSION 1
+
+struct slot_metadata {
+ // Slot priority with 15 meaning highest priority, 1 lowest
+ // priority and 0 the slot is unbootable.
+ uint8_t priority : 4;
+ // Number of times left attempting to boot this slot.
+ uint8_t tries_remaining : 3;
+ // 1 if this slot has booted successfully, 0 otherwise.
+ uint8_t successful_boot : 1;
+ // 1 if this slot is corrupted from a dm-verity corruption, 0
+ // otherwise.
+ uint8_t verity_corrupted : 1;
+ // Reserved for further use.
+ uint8_t reserved : 7;
+} __attribute__((packed));
+
+/* Bootloader Control AB
+ *
+ * This struct can be used to manage A/B metadata. It is designed to
+ * be put in the 'slot_suffix' field of the 'bootloader_message'
+ * structure described above. It is encouraged to use the
+ * 'bootloader_control' structure to store the A/B metadata, but not
+ * mandatory.
+ */
+struct bootloader_control {
+ // NUL terminated active slot suffix.
+ char slot_suffix[4];
+ // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
+ uint32_t magic;
+ // Version of struct being used (see BOOT_CTRL_VERSION).
+ uint8_t version;
+ // Number of slots being managed.
+ uint8_t nb_slot : 3;
+ // Number of times left attempting to boot recovery.
+ uint8_t recovery_tries_remaining : 3;
+ // Status of any pending snapshot merge of dynamic partitions.
+ uint8_t merge_status : 3;
+ // Ensure 4-bytes alignment for slot_info field.
+ uint8_t reserved0[1];
+ // Per-slot information. Up to 4 slots.
+ struct slot_metadata slot_info[4];
+ // Reserved for further use.
+ uint8_t reserved1[8];
+ // CRC32 of all 28 bytes preceding this field (little endian
+ // format).
+ uint32_t crc32_le;
+} __attribute__((packed));
+
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_control) ==
+ sizeof(((struct bootloader_message_ab *)0)->slot_suffix),
+ "struct bootloader_control has wrong size");
+#endif
+
diff --git a/boot/1.1/default/boot_control/legacy_boot_control.cpp b/boot/1.1/default/boot_control/legacy_boot_control.cpp
new file mode 100644
index 0000000..73d3a58
--- /dev/null
+++ b/boot/1.1/default/boot_control/legacy_boot_control.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+
+#include <libboot_control/libboot_control.h>
+
+using android::bootable::BootControl;
+
+struct boot_control_private_t {
+ // The base struct needs to be first in the list.
+ boot_control_module_t base;
+
+ BootControl impl;
+};
+
+namespace {
+
+void BootControl_init(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ impl.Init();
+}
+
+unsigned int BootControl_getNumberSlots(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.GetNumberSlots();
+}
+
+unsigned int BootControl_getCurrentSlot(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.GetCurrentSlot();
+}
+
+int BootControl_markBootSuccessful(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.MarkBootSuccessful() ? 0 : -1;
+}
+
+int BootControl_setActiveBootSlot(boot_control_module_t* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.SetActiveBootSlot(slot) ? 0 : -1;
+}
+
+int BootControl_setSlotAsUnbootable(struct boot_control_module* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.SetSlotAsUnbootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotBootable(struct boot_control_module* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.IsSlotBootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotMarkedSuccessful(struct boot_control_module* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.IsSlotMarkedSuccessful(slot) ? 0 : -1;
+}
+
+const char* BootControl_getSuffix(boot_control_module_t* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.GetSuffix(slot);
+}
+
+static int BootControl_open(const hw_module_t* module __unused, const char* id __unused,
+ hw_device_t** device __unused) {
+ /* Nothing to do currently. */
+ return 0;
+}
+
+struct hw_module_methods_t BootControl_methods = {
+ .open = BootControl_open,
+};
+
+} // namespace
+
+boot_control_private_t HAL_MODULE_INFO_SYM = {
+ .base =
+ {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = BOOT_CONTROL_HARDWARE_MODULE_ID,
+ .name = "AOSP reference bootctrl HAL",
+ .author = "The Android Open Source Project",
+ .methods = &BootControl_methods,
+ },
+ .init = BootControl_init,
+ .getNumberSlots = BootControl_getNumberSlots,
+ .getCurrentSlot = BootControl_getCurrentSlot,
+ .markBootSuccessful = BootControl_markBootSuccessful,
+ .setActiveBootSlot = BootControl_setActiveBootSlot,
+ .setSlotAsUnbootable = BootControl_setSlotAsUnbootable,
+ .isSlotBootable = BootControl_isSlotBootable,
+ .getSuffix = BootControl_getSuffix,
+ .isSlotMarkedSuccessful = BootControl_isSlotMarkedSuccessful,
+ },
+};
diff --git a/boot/1.1/default/boot_control/libboot_control.cpp b/boot/1.1/default/boot_control/libboot_control.cpp
new file mode 100644
index 0000000..2c6ccaf
--- /dev/null
+++ b/boot/1.1/default/boot_control/libboot_control.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libboot_control/libboot_control.h>
+
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <bootloader_message/bootloader_message.h>
+
+#include "private/boot_control_definition.h"
+
+namespace android {
+namespace bootable {
+
+using ::android::hardware::boot::V1_1::MergeStatus;
+
+// The number of boot attempts that should be made from a new slot before
+// rolling back to the previous slot.
+constexpr unsigned int kDefaultBootAttempts = 7;
+static_assert(kDefaultBootAttempts < 8, "tries_remaining field only has 3 bits");
+
+constexpr unsigned int kMaxNumSlots =
+ sizeof(bootloader_control::slot_info) / sizeof(bootloader_control::slot_info[0]);
+constexpr const char* kSlotSuffixes[kMaxNumSlots] = { "_a", "_b", "_c", "_d" };
+constexpr off_t kBootloaderControlOffset = offsetof(bootloader_message_ab, slot_suffix);
+
+static uint32_t CRC32(const uint8_t* buf, size_t size) {
+ static uint32_t crc_table[256];
+
+ // Compute the CRC-32 table only once.
+ if (!crc_table[1]) {
+ for (uint32_t i = 0; i < 256; ++i) {
+ uint32_t crc = i;
+ for (uint32_t j = 0; j < 8; ++j) {
+ uint32_t mask = -(crc & 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & mask);
+ }
+ crc_table[i] = crc;
+ }
+ }
+
+ uint32_t ret = -1;
+ for (size_t i = 0; i < size; ++i) {
+ ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
+ }
+
+ return ~ret;
+}
+
+// Return the little-endian representation of the CRC-32 of the first fields
+// in |boot_ctrl| up to the crc32_le field.
+uint32_t BootloaderControlLECRC(const bootloader_control* boot_ctrl) {
+ return htole32(
+ CRC32(reinterpret_cast<const uint8_t*>(boot_ctrl), offsetof(bootloader_control, crc32_le)));
+}
+
+bool LoadBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+ android::base::unique_fd fd(open(misc_device.c_str(), O_RDONLY));
+ if (fd.get() == -1) {
+ PLOG(ERROR) << "failed to open " << misc_device;
+ return false;
+ }
+ if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+ PLOG(ERROR) << "failed to lseek " << misc_device;
+ return false;
+ }
+ if (!android::base::ReadFully(fd.get(), buffer, sizeof(bootloader_control))) {
+ PLOG(ERROR) << "failed to read " << misc_device;
+ return false;
+ }
+ return true;
+}
+
+bool UpdateAndSaveBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+ buffer->crc32_le = BootloaderControlLECRC(buffer);
+ android::base::unique_fd fd(open(misc_device.c_str(), O_WRONLY | O_SYNC));
+ if (fd.get() == -1) {
+ PLOG(ERROR) << "failed to open " << misc_device;
+ return false;
+ }
+ if (lseek(fd.get(), kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+ PLOG(ERROR) << "failed to lseek " << misc_device;
+ return false;
+ }
+ if (!android::base::WriteFully(fd.get(), buffer, sizeof(bootloader_control))) {
+ PLOG(ERROR) << "failed to write " << misc_device;
+ return false;
+ }
+ return true;
+}
+
+void InitDefaultBootloaderControl(BootControl* control, bootloader_control* boot_ctrl) {
+ memset(boot_ctrl, 0, sizeof(*boot_ctrl));
+
+ unsigned int current_slot = control->GetCurrentSlot();
+ if (current_slot < kMaxNumSlots) {
+ strlcpy(boot_ctrl->slot_suffix, kSlotSuffixes[current_slot], sizeof(boot_ctrl->slot_suffix));
+ }
+ boot_ctrl->magic = BOOT_CTRL_MAGIC;
+ boot_ctrl->version = BOOT_CTRL_VERSION;
+
+ // Figure out the number of slots by checking if the partitions exist,
+ // otherwise assume the maximum supported by the header.
+ boot_ctrl->nb_slot = kMaxNumSlots;
+ std::string base_path = control->misc_device();
+ size_t last_path_sep = base_path.rfind('/');
+ if (last_path_sep != std::string::npos) {
+ // We test the existence of the "boot" partition on each possible slot,
+ // which is a partition required by Android Bootloader Requirements.
+ base_path = base_path.substr(0, last_path_sep + 1) + "boot";
+ int last_existing_slot = -1;
+ int first_missing_slot = -1;
+ for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+ std::string partition_path = base_path + kSlotSuffixes[slot];
+ struct stat part_stat;
+ int err = stat(partition_path.c_str(), &part_stat);
+ if (!err) {
+ last_existing_slot = slot;
+ LOG(INFO) << "Found slot: " << kSlotSuffixes[slot];
+ } else if (err < 0 && errno == ENOENT && first_missing_slot == -1) {
+ first_missing_slot = slot;
+ }
+ }
+ // We only declare that we found the actual number of slots if we found all
+ // the boot partitions up to the number of slots, and no boot partition
+ // after that. Not finding any of the boot partitions implies a problem so
+ // we just leave the number of slots in the maximum value.
+ if ((last_existing_slot != -1 && last_existing_slot + 1 == first_missing_slot) ||
+ (first_missing_slot == -1 && last_existing_slot + 1 == kMaxNumSlots)) {
+ boot_ctrl->nb_slot = last_existing_slot + 1;
+ LOG(INFO) << "Found a system with " << last_existing_slot + 1 << " slots.";
+ }
+ }
+
+ for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+ slot_metadata entry = {};
+
+ if (slot < boot_ctrl->nb_slot) {
+ entry.priority = 7;
+ entry.tries_remaining = kDefaultBootAttempts;
+ entry.successful_boot = 0;
+ } else {
+ entry.priority = 0; // Unbootable
+ }
+
+ // When the boot_control stored on disk is invalid, we assume that the
+ // current slot is successful. The bootloader should repair this situation
+ // before booting and write a valid boot_control slot, so if we reach this
+ // stage it means that the misc partition was corrupted since boot.
+ if (current_slot == slot) {
+ entry.successful_boot = 1;
+ }
+
+ boot_ctrl->slot_info[slot] = entry;
+ }
+ boot_ctrl->recovery_tries_remaining = 0;
+
+ boot_ctrl->crc32_le = BootloaderControlLECRC(boot_ctrl);
+}
+
+// Return the index of the slot suffix passed or -1 if not a valid slot suffix.
+int SlotSuffixToIndex(const char* suffix) {
+ for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+ if (!strcmp(kSlotSuffixes[slot], suffix)) return slot;
+ }
+ return -1;
+}
+
+// Initialize the boot_control_private struct with the information from
+// the bootloader_message buffer stored in |boot_ctrl|. Returns whether the
+// initialization succeeded.
+bool BootControl::Init() {
+ if (initialized_) return true;
+
+ // Initialize the current_slot from the read-only property. If the property
+ // was not set (from either the command line or the device tree), we can later
+ // initialize it from the bootloader_control struct.
+ std::string suffix_prop = android::base::GetProperty("ro.boot.slot_suffix", "");
+ if (suffix_prop.empty()) {
+ LOG(ERROR) << "Slot suffix property is not set";
+ return false;
+ }
+ current_slot_ = SlotSuffixToIndex(suffix_prop.c_str());
+
+ std::string err;
+ std::string device = get_bootloader_message_blk_device(&err);
+ if (device.empty()) {
+ LOG(ERROR) << "Could not find bootloader message block device: " << err;
+ return false;
+ }
+
+ bootloader_control boot_ctrl;
+ if (!LoadBootloaderControl(device.c_str(), &boot_ctrl)) {
+ LOG(ERROR) << "Failed to load bootloader control block";
+ return false;
+ }
+
+ // Note that since there isn't a module unload function this memory is leaked.
+ // We use `device` below sometimes, so it's not moved out of here.
+ misc_device_ = device;
+ initialized_ = true;
+
+ // Validate the loaded data, otherwise we will destroy it and re-initialize it
+ // with the current information.
+ uint32_t computed_crc32 = BootloaderControlLECRC(&boot_ctrl);
+ if (boot_ctrl.crc32_le != computed_crc32) {
+ LOG(WARNING) << "Invalid boot control found, expected CRC-32 0x" << std::hex << computed_crc32
+ << " but found 0x" << std::hex << boot_ctrl.crc32_le << ". Re-initializing.";
+ InitDefaultBootloaderControl(this, &boot_ctrl);
+ UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl);
+ }
+
+ if (!InitMiscVirtualAbMessageIfNeeded()) {
+ return false;
+ }
+
+ num_slots_ = boot_ctrl.nb_slot;
+ return true;
+}
+
+unsigned int BootControl::GetNumberSlots() {
+ return num_slots_;
+}
+
+unsigned int BootControl::GetCurrentSlot() {
+ return current_slot_;
+}
+
+bool BootControl::MarkBootSuccessful() {
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ bootctrl.slot_info[current_slot_].successful_boot = 1;
+ // tries_remaining == 0 means that the slot is not bootable anymore, make
+ // sure we mark the current slot as bootable if it succeeds in the last
+ // attempt.
+ bootctrl.slot_info[current_slot_].tries_remaining = 1;
+ return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetActiveBootSlot(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ // Set every other slot with a lower priority than the new "active" slot.
+ const unsigned int kActivePriority = 15;
+ const unsigned int kActiveTries = 6;
+ for (unsigned int i = 0; i < num_slots_; ++i) {
+ if (i != slot) {
+ if (bootctrl.slot_info[i].priority >= kActivePriority)
+ bootctrl.slot_info[i].priority = kActivePriority - 1;
+ }
+ }
+
+ // Note that setting a slot as active doesn't change the successful bit.
+ // The successful bit will only be changed by setSlotAsUnbootable().
+ bootctrl.slot_info[slot].priority = kActivePriority;
+ bootctrl.slot_info[slot].tries_remaining = kActiveTries;
+
+ // Setting the current slot as active is a way to revert the operation that
+ // set *another* slot as active at the end of an updater. This is commonly
+ // used to cancel the pending update. We should only reset the verity_corrpted
+ // bit when attempting a new slot, otherwise the verity bit on the current
+ // slot would be flip.
+ if (slot != current_slot_) bootctrl.slot_info[slot].verity_corrupted = 0;
+
+ return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetSlotAsUnbootable(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ // The only way to mark a slot as unbootable, regardless of the priority is to
+ // set the tries_remaining to 0.
+ bootctrl.slot_info[slot].successful_boot = 0;
+ bootctrl.slot_info[slot].tries_remaining = 0;
+ return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::IsSlotBootable(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ return bootctrl.slot_info[slot].tries_remaining != 0;
+}
+
+bool BootControl::IsSlotMarkedSuccessful(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ return bootctrl.slot_info[slot].successful_boot && bootctrl.slot_info[slot].tries_remaining;
+}
+
+bool BootControl::IsValidSlot(unsigned int slot) {
+ return slot < kMaxNumSlots && slot < num_slots_;
+}
+
+bool BootControl::SetSnapshotMergeStatus(MergeStatus status) {
+ return SetMiscVirtualAbMergeStatus(current_slot_, status);
+}
+
+MergeStatus BootControl::GetSnapshotMergeStatus() {
+ MergeStatus status;
+ if (!GetMiscVirtualAbMergeStatus(current_slot_, &status)) {
+ return MergeStatus::UNKNOWN;
+ }
+ return status;
+}
+
+const char* BootControl::GetSuffix(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ return nullptr;
+ }
+ return kSlotSuffixes[slot];
+}
+
+bool InitMiscVirtualAbMessageIfNeeded() {
+ std::string err;
+ misc_virtual_ab_message message;
+ if (!ReadMiscVirtualAbMessage(&message, &err)) {
+ LOG(ERROR) << "Could not read merge status: " << err;
+ return false;
+ }
+
+ if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION &&
+ message.magic == MISC_VIRTUAL_AB_MAGIC_HEADER) {
+ // Already initialized.
+ return true;
+ }
+
+ message = {};
+ message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION;
+ message.magic = MISC_VIRTUAL_AB_MAGIC_HEADER;
+ if (!WriteMiscVirtualAbMessage(message, &err)) {
+ LOG(ERROR) << "Could not write merge status: " << err;
+ return false;
+ }
+ return true;
+}
+
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus status) {
+ std::string err;
+ misc_virtual_ab_message message;
+
+ if (!ReadMiscVirtualAbMessage(&message, &err)) {
+ LOG(ERROR) << "Could not read merge status: " << err;
+ return false;
+ }
+
+ message.merge_status = static_cast<uint8_t>(status);
+ message.source_slot = current_slot;
+ if (!WriteMiscVirtualAbMessage(message, &err)) {
+ LOG(ERROR) << "Could not write merge status: " << err;
+ return false;
+ }
+ return true;
+}
+
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus* status) {
+ std::string err;
+ misc_virtual_ab_message message;
+
+ if (!ReadMiscVirtualAbMessage(&message, &err)) {
+ LOG(ERROR) << "Could not read merge status: " << err;
+ return false;
+ }
+
+ // If the slot reverted after having created a snapshot, then the snapshot will
+ // be thrown away at boot. Thus we don't count this as being in a snapshotted
+ // state.
+ *status = static_cast<MergeStatus>(message.merge_status);
+ if (*status == MergeStatus::SNAPSHOTTED && current_slot == message.source_slot) {
+ *status = MergeStatus::NONE;
+ }
+ return true;
+}
+
+} // namespace bootable
+} // namespace android
diff --git a/camera/common/1.0/default/Exif.cpp b/camera/common/1.0/default/Exif.cpp
index 4de05c5..413b6bb 100644
--- a/camera/common/1.0/default/Exif.cpp
+++ b/camera/common/1.0/default/Exif.cpp
@@ -632,13 +632,13 @@
}
bool ExifUtilsImpl::setImageHeight(uint32_t length) {
- SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
+ SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION, length);
return true;
}
bool ExifUtilsImpl::setImageWidth(uint32_t width) {
- SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
+ SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION, width);
return true;
}
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index f518a15..677b496 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -20,6 +20,7 @@
#include <algorithm>
#include <array>
+#include <regex>
#include <linux/videodev2.h>
#include "android-base/macros.h"
#include "CameraMetadata.h"
@@ -46,10 +47,20 @@
} // anonymous namespace
+const std::regex kDevicePathRE("/dev/video([0-9]+)");
+
ExternalCameraDevice::ExternalCameraDevice(
- const std::string& cameraId, const ExternalCameraConfig& cfg) :
- mCameraId(cameraId),
- mCfg(cfg) {}
+ const std::string& devicePath, const ExternalCameraConfig& cfg) :
+ mCameraId("-1"),
+ mDevicePath(devicePath),
+ mCfg(cfg) {
+ std::smatch sm;
+ if (std::regex_match(mDevicePath, sm, kDevicePathRE)) {
+ mCameraId = std::to_string(mCfg.cameraIdOffset + std::stoi(sm[1]));
+ } else {
+ ALOGE("%s: device path match failed for %s", __FUNCTION__, mDevicePath.c_str());
+ }
+}
ExternalCameraDevice::~ExternalCameraDevice() {}
@@ -129,20 +140,20 @@
return Void();
}
- unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
+ unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
if (fd.get() < 0) {
int numAttempt = 0;
do {
ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again",
- __FUNCTION__, mCameraId.c_str());
+ __FUNCTION__, mDevicePath.c_str());
usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
- fd.reset(::open(mCameraId.c_str(), O_RDWR));
+ fd.reset(::open(mDevicePath.c_str(), O_RDWR));
numAttempt++;
} while (fd.get() < 0 && numAttempt <= MAX_RETRY);
if (fd.get() < 0) {
ALOGE("%s: v4l2 device open %s failed: %s",
- __FUNCTION__, mCameraId.c_str(), strerror(errno));
+ __FUNCTION__, mDevicePath.c_str(), strerror(errno));
mLock.unlock();
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
@@ -203,9 +214,9 @@
status_t ExternalCameraDevice::initCameraCharacteristics() {
if (mCameraCharacteristics.isEmpty()) {
// init camera characteristics
- unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
+ unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
if (fd.get() < 0) {
- ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
+ ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mDevicePath.c_str());
return DEAD_OBJECT;
}
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 62a4c87..8f4626c 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -703,6 +703,7 @@
namespace common {
namespace {
+ const int kDefaultCameraIdOffset = 100;
const int kDefaultJpegBufSize = 5 << 20; // 5MB
const int kDefaultNumVideoBuffer = 4;
const int kDefaultNumStillBuffer = 2;
@@ -738,6 +739,11 @@
return ret;
}
+ XMLElement *cameraIdOffset = providerCfg->FirstChildElement("CameraIdOffset");
+ if (cameraIdOffset != nullptr) {
+ ret.cameraIdOffset = std::atoi(cameraIdOffset->GetText());
+ }
+
XMLElement *ignore = providerCfg->FirstChildElement("ignore");
if (ignore == nullptr) {
ALOGI("%s: no internal ignored device specified", __FUNCTION__);
@@ -874,6 +880,7 @@
}
ExternalCameraConfig::ExternalCameraConfig() :
+ cameraIdOffset(kDefaultCameraIdOffset),
maxJpegBufSize(kDefaultJpegBufSize),
numVideoBuffers(kDefaultNumVideoBuffer),
numStillBuffers(kDefaultNumStillBuffer),
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
index 1958fcb..88726f4 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -149,6 +149,7 @@
bool mInitialized = false;
bool mInitFailed = false;
std::string mCameraId;
+ std::string mDevicePath;
const ExternalCameraConfig& mCfg;
std::vector<SupportedV4L2Format> mSupportedFormats;
CroppingType mCroppingType;
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 74f75eb..b354406 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -68,6 +68,9 @@
static const char* kDefaultCfgPath;
static ExternalCameraConfig loadFromCfg(const char* cfgPath = kDefaultCfgPath);
+ // CameraId base offset for numerical representation
+ uint32_t cameraIdOffset;
+
// List of internal V4L2 video nodes external camera HAL must ignore.
std::unordered_set<std::string> mInternalDevices;
diff --git a/camera/device/3.6/default/ExternalCameraDeviceSession.cpp b/camera/device/3.6/default/ExternalCameraDeviceSession.cpp
index 60a1a10..8fd8e58 100644
--- a/camera/device/3.6/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.6/default/ExternalCameraDeviceSession.cpp
@@ -272,16 +272,17 @@
// convert hal requests to offline request
std::deque<std::shared_ptr<HalRequest>> offlineReqs(halReqs.size());
+ size_t i = 0;
for (auto& v4lReq : halReqs) {
- std::shared_ptr<HalRequest> halReq = std::make_shared<HalRequest>();
- halReq->frameNumber = v4lReq->frameNumber;
- halReq->setting = v4lReq->setting;
- halReq->shutterTs = v4lReq->shutterTs;
- halReq->buffers = v4lReq->buffers;
+ offlineReqs[i] = std::make_shared<HalRequest>();
+ offlineReqs[i]->frameNumber = v4lReq->frameNumber;
+ offlineReqs[i]->setting = v4lReq->setting;
+ offlineReqs[i]->shutterTs = v4lReq->shutterTs;
+ offlineReqs[i]->buffers = v4lReq->buffers;
sp<V3_4::implementation::V4L2Frame> v4l2Frame =
static_cast<V3_4::implementation::V4L2Frame*>(v4lReq->frameIn.get());
- halReq->frameIn = new AllocatedV4L2Frame(v4l2Frame);
- offlineReqs.push_back(halReq);
+ offlineReqs[i]->frameIn = new AllocatedV4L2Frame(v4l2Frame);
+ i++;
// enqueue V4L2 frame
enqueueV4l2Frame(v4l2Frame);
}
diff --git a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
index 2bfced2..64a51f6 100644
--- a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
@@ -44,17 +44,19 @@
const char* kDevicePath = "/dev/";
constexpr char kPrefix[] = "video";
constexpr int kPrefixLen = sizeof(kPrefix) - 1;
+constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
-bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion,
- std::string* cameraId) {
+bool matchDeviceName(int cameraIdOffset,
+ const hidl_string& deviceName, std::string* deviceVersion,
+ std::string* cameraDevicePath) {
std::string deviceNameStd(deviceName.c_str());
std::smatch sm;
if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
if (deviceVersion != nullptr) {
*deviceVersion = sm[1];
}
- if (cameraId != nullptr) {
- *cameraId = sm[2];
+ if (cameraDevicePath != nullptr) {
+ *cameraDevicePath = "/dev/video" + std::to_string(std::stoi(sm[2]) - cameraIdOffset);
}
return true;
}
@@ -146,8 +148,9 @@
const hidl_string& cameraDeviceName,
ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) {
- std::string cameraId, deviceVersion;
- bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
+ std::string cameraDevicePath, deviceVersion;
+ bool match = matchDeviceName(mCfg.cameraIdOffset, cameraDeviceName,
+ &deviceVersion, &cameraDevicePath);
if (!match) {
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
@@ -164,19 +167,19 @@
case 4: {
ALOGV("Constructing v3.4 external camera device");
deviceImpl = new device::V3_4::implementation::ExternalCameraDevice(
- cameraId, mCfg);
+ cameraDevicePath, mCfg);
break;
}
case 5: {
ALOGV("Constructing v3.5 external camera device");
deviceImpl = new device::V3_5::implementation::ExternalCameraDevice(
- cameraId, mCfg);
+ cameraDevicePath, mCfg);
break;
}
case 6: {
ALOGV("Constructing v3.6 external camera device");
deviceImpl = new device::V3_6::implementation::ExternalCameraDevice(
- cameraId, mCfg);
+ cameraDevicePath, mCfg);
break;
}
default:
@@ -186,7 +189,7 @@
}
if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
- ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
+ ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraDevicePath.c_str());
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
@@ -210,12 +213,14 @@
ALOGI("ExtCam: adding %s to External Camera HAL!", devName);
Mutex::Autolock _l(mLock);
std::string deviceName;
+ std::string cameraId = std::to_string(mCfg.cameraIdOffset +
+ std::atoi(devName + kDevicePrefixLen));
if (mPreferredHal3MinorVersion == 6) {
- deviceName = std::string("device@3.6/external/") + devName;
+ deviceName = std::string("device@3.6/external/") + cameraId;
} else if (mPreferredHal3MinorVersion == 5) {
- deviceName = std::string("device@3.5/external/") + devName;
+ deviceName = std::string("device@3.5/external/") + cameraId;
} else {
- deviceName = std::string("device@3.4/external/") + devName;
+ deviceName = std::string("device@3.4/external/") + cameraId;
}
mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
if (mCallbacks != nullptr) {
@@ -259,12 +264,14 @@
void ExternalCameraProviderImpl_2_4::deviceRemoved(const char* devName) {
Mutex::Autolock _l(mLock);
std::string deviceName;
+ std::string cameraId = std::to_string(mCfg.cameraIdOffset +
+ std::atoi(devName + kDevicePrefixLen));
if (mPreferredHal3MinorVersion == 6) {
- deviceName = std::string("device@3.6/external/") + devName;
+ deviceName = std::string("device@3.6/external/") + cameraId;
} else if (mPreferredHal3MinorVersion == 5) {
- deviceName = std::string("device@3.5/external/") + devName;
+ deviceName = std::string("device@3.5/external/") + cameraId;
} else {
- deviceName = std::string("device@3.4/external/") + devName;
+ deviceName = std::string("device@3.4/external/") + cameraId;
}
if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
mCameraStatusMap.erase(deviceName);
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 5c73aa2..c9d76da 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -69,65 +69,67 @@
#include <android/hidl/memory/1.0/IMemory.h>
using namespace ::android::hardware::camera::device;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
+using ::android::BufferItemConsumer;
+using ::android::BufferQueue;
+using ::android::GraphicBuffer;
+using ::android::IGraphicBufferConsumer;
+using ::android::IGraphicBufferProducer;
+using ::android::sp;
+using ::android::Surface;
+using ::android::wp;
using ::android::hardware::hidl_bitfield;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
-using ::android::sp;
-using ::android::wp;
-using ::android::GraphicBuffer;
-using ::android::IGraphicBufferProducer;
-using ::android::IGraphicBufferConsumer;
-using ::android::BufferQueue;
-using ::android::BufferItemConsumer;
-using ::android::Surface;
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using ::android::hardware::graphics::common::V1_0::Dataspace;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::TorchMode;
using ::android::hardware::camera::common::V1_0::TorchModeStatus;
using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
using ::android::hardware::camera::common::V1_0::helper::Size;
-using ::android::hardware::camera::provider::V2_4::ICameraProvider;
-using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
-using ::android::hardware::camera::device::V3_2::ICameraDevice;
-using ::android::hardware::camera::device::V3_2::BufferCache;
-using ::android::hardware::camera::device::V3_2::CaptureRequest;
-using ::android::hardware::camera::device::V3_2::CaptureResult;
-using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
-using ::android::hardware::camera::device::V3_2::NotifyMsg;
-using ::android::hardware::camera::device::V3_2::RequestTemplate;
-using ::android::hardware::camera::device::V3_2::StreamType;
-using ::android::hardware::camera::device::V3_2::StreamRotation;
-using ::android::hardware::camera::device::V3_2::StreamConfiguration;
-using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
-using ::android::hardware::camera::device::V3_2::CameraMetadata;
-using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
-using ::android::hardware::camera::device::V3_2::BufferStatus;
-using ::android::hardware::camera::device::V3_2::StreamBuffer;
-using ::android::hardware::camera::device::V3_2::MsgType;
-using ::android::hardware::camera::device::V3_2::ErrorMsg;
-using ::android::hardware::camera::device::V3_2::ErrorCode;
using ::android::hardware::camera::device::V1_0::CameraFacing;
-using ::android::hardware::camera::device::V1_0::NotifyCallbackMsg;
+using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
using ::android::hardware::camera::device::V1_0::CommandType;
using ::android::hardware::camera::device::V1_0::DataCallbackMsg;
-using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
-using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
using ::android::hardware::camera::device::V1_0::FrameCallbackFlag;
using ::android::hardware::camera::device::V1_0::HandleTimestampMessage;
-using ::android::hardware::camera::metadata::V3_4::CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
-using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
+using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
+using ::android::hardware::camera::device::V1_0::NotifyCallbackMsg;
+using ::android::hardware::camera::device::V3_2::BufferCache;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::CaptureResult;
+using ::android::hardware::camera::device::V3_2::ErrorCode;
+using ::android::hardware::camera::device::V3_2::ErrorMsg;
+using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_2::ICameraDevice;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
+using ::android::hardware::camera::device::V3_2::MsgType;
+using ::android::hardware::camera::device::V3_2::NotifyMsg;
+using ::android::hardware::camera::device::V3_2::RequestTemplate;
+using ::android::hardware::camera::device::V3_2::StreamBuffer;
+using ::android::hardware::camera::device::V3_2::StreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
+using ::android::hardware::camera::device::V3_2::StreamRotation;
+using ::android::hardware::camera::device::V3_2::StreamType;
using ::android::hardware::camera::device::V3_4::PhysicalCameraMetadata;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::camera::metadata::V3_4::
+ CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
+using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
+using ::android::hardware::camera::provider::V2_4::ICameraProvider;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
+using ::android::hidl::memory::V1_0::IMemory;
using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
using ::android::hidl::manager::V1_0::IServiceManager;
@@ -554,7 +556,12 @@
hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
- struct EmptyDeviceCb : public V3_5::ICameraDeviceCallback {
+ std::map<hidl_string, hidl_string> getCameraDeviceIdToNameMap(sp<ICameraProvider> provider);
+
+ hidl_vec<hidl_vec<hidl_string>> getConcurrentDeviceCombinations(
+ sp<::android::hardware::camera::provider::V2_6::ICameraProvider>&);
+
+ struct EmptyDeviceCb : public V3_5::ICameraDeviceCallback {
virtual Return<void> processCaptureResult(
const hidl_vec<CaptureResult>& /*results*/) override {
ALOGI("processCaptureResult callback");
@@ -591,8 +598,7 @@
ADD_FAILURE(); // Empty callback should not reach here
return Void();
}
-
- };
+ };
struct DeviceCb : public V3_5::ICameraDeviceCallback {
DeviceCb(CameraHidlTest *parent, int deviceVersion, const camera_metadata_t *staticMeta) :
@@ -808,6 +814,13 @@
static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta,
std::vector<AvailableStream> &outputStreams,
const AvailableStream *threshold = nullptr);
+
+ static Status getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, PixelFormat format,
+ Size* size);
+
+ static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
+ std::vector<AvailableStream>* outputStreams);
+
static Status getJpegBufferSize(camera_metadata_t *staticMeta,
uint32_t* outBufSize);
static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
@@ -1535,6 +1548,20 @@
return Void();
}
+std::map<hidl_string, hidl_string> CameraHidlTest::getCameraDeviceIdToNameMap(
+ sp<ICameraProvider> provider) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(provider);
+ std::map<hidl_string, hidl_string> idToNameMap;
+ for (auto& name : cameraDeviceNames) {
+ std::string version, cameraId;
+ if (!matchDeviceName(name, mProviderType, &version, &cameraId)) {
+ ADD_FAILURE();
+ }
+ idToNameMap.insert(std::make_pair(hidl_string(cameraId), name));
+ }
+ return idToNameMap;
+}
+
hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider) {
std::vector<std::string> cameraDeviceNames;
Return<void> ret;
@@ -1591,6 +1618,21 @@
return retList;
}
+hidl_vec<hidl_vec<hidl_string>> CameraHidlTest::getConcurrentDeviceCombinations(
+ sp<::android::hardware::camera::provider::V2_6::ICameraProvider>& provider2_6) {
+ hidl_vec<hidl_vec<hidl_string>> combinations;
+ Return<void> ret = provider2_6->getConcurrentStreamingCameraIds(
+ [&combinations](Status concurrentIdStatus,
+ const hidl_vec<hidl_vec<hidl_string>>& cameraDeviceIdCombinations) {
+ ASSERT_EQ(concurrentIdStatus, Status::OK);
+ combinations = cameraDeviceIdCombinations;
+ });
+ if (!ret.isOk()) {
+ ADD_FAILURE();
+ }
+ return combinations;
+}
+
// Test devices with first_api_level >= P does not advertise device@1.0
TEST_P(CameraHidlTest, noHal1AfterP) {
constexpr int32_t HAL1_PHASE_OUT_API_LEVEL = 28;
@@ -3078,6 +3120,157 @@
}
}
+// Verify that mandatory concurrent streams and outputs are supported.
+TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) {
+ struct CameraTestInfo {
+ camera_metadata_t* staticMeta = nullptr;
+ sp<ICameraDeviceSession> session;
+ sp<device::V3_3::ICameraDeviceSession> session3_3;
+ sp<device::V3_4::ICameraDeviceSession> session3_4;
+ sp<device::V3_5::ICameraDeviceSession> session3_5;
+ sp<device::V3_6::ICameraDeviceSession> session3_6;
+ sp<device::V3_2::ICameraDevice> cameraDevice;
+ sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+ ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
+ ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+ ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+ };
+ if (mProvider2_6 == nullptr) {
+ // This test is provider@2.6 specific
+ ALOGW("%s provider not 2_6, skipping", __func__);
+ return;
+ }
+
+ std::map<hidl_string, hidl_string> idToNameMap = getCameraDeviceIdToNameMap(mProvider2_6);
+ hidl_vec<hidl_vec<hidl_string>> concurrentDeviceCombinations =
+ getConcurrentDeviceCombinations(mProvider2_6);
+ std::vector<AvailableStream> outputStreams;
+ for (const auto& cameraDeviceIds : concurrentDeviceCombinations) {
+ std::vector<CameraIdAndStreamCombination> cameraIdsAndStreamCombinations;
+ std::vector<CameraTestInfo> cameraTestInfos;
+ size_t i = 0;
+ for (const auto& id : cameraDeviceIds) {
+ CameraTestInfo cti;
+ Return<void> ret;
+ auto it = idToNameMap.find(id);
+ ASSERT_TRUE(idToNameMap.end() != it);
+ hidl_string name = it->second;
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ if (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) {
+ continue;
+ } else if (deviceVersion <= 0) {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ return;
+ }
+ openEmptyDeviceSession(name, mProvider2_6, &cti.session /*out*/,
+ &cti.staticMeta /*out*/, &cti.cameraDevice /*out*/);
+ castSession(cti.session, deviceVersion, &cti.session3_3, &cti.session3_4,
+ &cti.session3_5, &cti.session3_6);
+ castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5);
+
+ outputStreams.clear();
+ ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(cti.staticMeta, &outputStreams));
+ ASSERT_NE(0u, outputStreams.size());
+
+ uint32_t jpegBufferSize = 0;
+ ASSERT_EQ(Status::OK, getJpegBufferSize(cti.staticMeta, &jpegBufferSize));
+ ASSERT_NE(0u, jpegBufferSize);
+
+ int32_t streamId = 0;
+ ::android::hardware::hidl_vec<V3_2::Stream> streams3_2(outputStreams.size());
+ size_t j = 0;
+ for (const auto& it : outputStreams) {
+ V3_2::Stream stream3_2;
+ V3_2::DataspaceFlags dataspaceFlag = 0;
+ switch (static_cast<PixelFormat>(it.format)) {
+ case PixelFormat::BLOB:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
+ break;
+ case PixelFormat::Y16:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
+ break;
+ default:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
+ }
+ stream3_2 = {streamId++,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(it.width),
+ static_cast<uint32_t>(it.height),
+ static_cast<PixelFormat>(it.format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ dataspaceFlag,
+ StreamRotation::ROTATION_0};
+ streams3_2[j] = stream3_2;
+ j++;
+ }
+
+ // Add the created stream configs to cameraIdsAndStreamCombinations
+ createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
+ &cti.config3_2, &cti.config3_4, &cti.config3_5,
+ jpegBufferSize);
+
+ cti.config3_5.streamConfigCounter = outputStreams.size();
+ CameraIdAndStreamCombination cameraIdAndStreamCombination;
+ cameraIdAndStreamCombination.cameraId = id;
+ cameraIdAndStreamCombination.streamConfiguration = cti.config3_4;
+ cameraIdsAndStreamCombinations.push_back(cameraIdAndStreamCombination);
+ i++;
+ cameraTestInfos.push_back(cti);
+ }
+ // Now verify that concurrent streams are supported
+ auto cb = [](Status s, bool supported) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(supported, true);
+ };
+
+ auto ret = mProvider2_6->isConcurrentStreamCombinationSupported(
+ cameraIdsAndStreamCombinations, cb);
+
+ // Test the stream can actually be configured
+ for (const auto& cti : cameraTestInfos) {
+ if (cti.session3_5 != nullptr) {
+ bool expectStreamCombQuery = (isLogicalMultiCamera(cti.staticMeta) == Status::OK);
+ verifyStreamCombination(cti.cameraDevice3_5, cti.config3_4,
+ /*expectedStatus*/ true, expectStreamCombQuery);
+ ret = cti.session3_5->configureStreams_3_5(
+ cti.config3_5,
+ [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_5.v3_4.streams.size(), halConfig.streams.size());
+ });
+ } else if (cti.session3_4 != nullptr) {
+ ret = cti.session3_4->configureStreams_3_4(
+ cti.config3_4,
+ [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_4.streams.size(), halConfig.streams.size());
+ });
+ } else if (cti.session3_3 != nullptr) {
+ ret = cti.session3_3->configureStreams_3_3(
+ cti.config3_2,
+ [&cti](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_2.streams.size(), halConfig.streams.size());
+ });
+ } else {
+ ret = cti.session->configureStreams(
+ cti.config3_2, [&cti](Status s, HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_2.streams.size(), halConfig.streams.size());
+ });
+ }
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ for (const auto& cti : cameraTestInfos) {
+ free_camera_metadata(cti.staticMeta);
+ ret = cti.session->close();
+ ASSERT_TRUE(ret.isOk());
+ }
+ }
+}
+
// Check for correct handling of invalid/incorrect configuration parameters.
TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) {
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -5158,6 +5351,65 @@
return Status::OK;
}
+static Size getMinSize(Size a, Size b) {
+ if (a.width * a.height < b.width * b.height) {
+ return a;
+ }
+ return b;
+}
+
+// TODO: Add more combinations
+Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
+ std::vector<AvailableStream>* outputStreams) {
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ Size yuvMaxSize(1280, 720);
+ Size jpegMaxSize(1920, 1440);
+ Size maxAvailableYuvSize;
+ Size maxAvailableJpegSize;
+ getMaxOutputSizeForFormat(staticMeta, PixelFormat::YCBCR_420_888, &maxAvailableYuvSize);
+ getMaxOutputSizeForFormat(staticMeta, PixelFormat::BLOB, &maxAvailableJpegSize);
+ Size yuvChosenSize = getMinSize(yuvMaxSize, maxAvailableYuvSize);
+ Size jpegChosenSize = getMinSize(jpegMaxSize, maxAvailableJpegSize);
+
+ AvailableStream yuvStream = {.width = yuvChosenSize.width,
+ .height = yuvChosenSize.height,
+ .format = static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
+
+ AvailableStream jpegStream = {.width = jpegChosenSize.width,
+ .height = jpegChosenSize.height,
+ .format = static_cast<int32_t>(PixelFormat::BLOB)};
+ outputStreams->push_back(yuvStream);
+ outputStreams->push_back(jpegStream);
+
+ return Status::OK;
+}
+
+Status CameraHidlTest::getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta,
+ PixelFormat format, Size* size) {
+ std::vector<AvailableStream> outputStreams;
+ if (size == nullptr || getAvailableOutputStreams(staticMeta, outputStreams) != Status::OK) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ Size maxSize;
+ bool found = false;
+ for (auto& outputStream : outputStreams) {
+ if (static_cast<int32_t>(format) == outputStream.format &&
+ (outputStream.width * outputStream.height > maxSize.width * maxSize.height)) {
+ maxSize.width = outputStream.width;
+ maxSize.height = outputStream.height;
+ found = true;
+ }
+ }
+ if (!found) {
+ ALOGE("%s :chosen format %d not found", __FUNCTION__, static_cast<int32_t>(format));
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ *size = maxSize;
+ return Status::OK;
+}
+
void CameraHidlTest::fillOutputStreams(camera_metadata_ro_entry_t* entry,
std::vector<AvailableStream>& outputStreams, const AvailableStream* threshold,
const int32_t availableConfigOutputTag) {
diff --git a/camera/provider/2.6/ICameraProvider.hal b/camera/provider/2.6/ICameraProvider.hal
index 9c46ba0..5651550 100644
--- a/camera/provider/2.6/ICameraProvider.hal
+++ b/camera/provider/2.6/ICameraProvider.hal
@@ -56,11 +56,26 @@
* s720p - min (max output resolution for the given format, 1280 X 720)
* s1440p - min (max output resolution for the given format, 1920 X 1440)
*
+ * If a device has MONOCHROME capability (device's capabilities include
+ * ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) and therefore supports Y8
+ * outputs, stream combinations mentioned above, where YUV is substituted by
+ * Y8 must be also supported.
+ *
* The camera framework must call this method whenever it gets a
* cameraDeviceStatusChange callback adding a new camera device or removing
* a camera device known to it. This is so that the camera framework can get new combinations
* of camera ids that can stream concurrently, that might have potentially appeared.
*
+ * For each combination (and their subsets) of camera device ids returned by
+ * getConcurrentStreamingCameraIds(): If only the mandatory combinations can
+ * be supported concurrently by each device, then the resource costs must
+ * sum up to > 100 for the concurrent set, to ensure arbitration between
+ * camera applications work as expected. Only if resources are sufficient
+ * to run a set of cameras at full capability (maximally
+ * resource-consuming framerate and stream size settings available in the
+ * configuration settings exposed through camera metadata), should the sum
+ * of resource costs for the combination be <= 100.
+ *
* @return status Status code for the operation
* @return cameraIds a list of camera id combinations that support
* concurrent stream configurations with the minimum guarantees
diff --git a/cas/1.2/vts/functional/Android.bp b/cas/1.2/vts/functional/Android.bp
index 9bc372c..2d6517f 100644
--- a/cas/1.2/vts/functional/Android.bp
+++ b/cas/1.2/vts/functional/Android.bp
@@ -31,6 +31,8 @@
shared_libs: [
"libbinder",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts-core",
+ ],
}
-
diff --git a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
index 8439ceb..58e0f2e 100644
--- a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
+++ b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
@@ -16,8 +16,6 @@
#define LOG_TAG "mediacas_hidl_hal_test"
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
#include <android/hardware/cas/1.0/IDescramblerBase.h>
#include <android/hardware/cas/1.0/types.h>
@@ -28,8 +26,11 @@
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/cas/native/1.0/types.h>
#include <binder/MemoryDealer.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
#include <hidlmemory/FrameworkUtils.h>
#include <utils/Condition.h>
@@ -293,27 +294,14 @@
EXPECT_EQ(mEventArg, static_cast<int32_t>(mode));
}
-// Test environment for Cas HIDL HAL.
-class CasHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static CasHidlEnvironment* Instance() {
- static CasHidlEnvironment* instance = new CasHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override { registerTestService<IMediaCasService>(); }
-};
-
-class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class MediaCasHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
- mService = ::testing::VtsHalHidlTargetTestBase::getService<IMediaCasService>(
- CasHidlEnvironment::Instance()->getServiceName<IMediaCasService>());
+ mService = IMediaCasService::getService(GetParam());
ASSERT_NE(mService, nullptr);
}
- sp<IMediaCasService> mService;
+ sp<IMediaCasService> mService = nullptr;
protected:
static void description(const std::string& description) {
@@ -497,7 +485,7 @@
return ::testing::AssertionResult(returnVoid.isOk());
}
-TEST_F(MediaCasHidlTest, TestClearKeyApisWithSession) {
+TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) {
description("Test that valid call sequences with SessionEvent send and receive");
ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
@@ -609,11 +597,7 @@
} // anonymous namespace
-int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(CasHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- CasHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, MediaCasHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMediaCasService::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/compatibility_matrices/compatibility_matrix.1.xml b/compatibility_matrices/compatibility_matrix.1.xml
index d82829d..cccf24f 100644
--- a/compatibility_matrices/compatibility_matrix.1.xml
+++ b/compatibility_matrices/compatibility_matrix.1.xml
@@ -71,7 +71,7 @@
<instance>legacy/0</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
<name>android.hardware.configstore</name>
<version>1.0</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.2.xml b/compatibility_matrices/compatibility_matrix.2.xml
index 98e6cfa..d4f9809 100644
--- a/compatibility_matrices/compatibility_matrix.2.xml
+++ b/compatibility_matrices/compatibility_matrix.2.xml
@@ -79,7 +79,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
<name>android.hardware.configstore</name>
<version>1.0</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index 9933b33..5888ab9 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -111,7 +111,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
<name>android.hardware.configstore</name>
<version>1.0-1</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 1861b1c..c5a9102 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -40,6 +40,18 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.automotive.can</name>
+ <version>1.0</version>
+ <interface>
+ <name>ICanBus</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ <interface>
+ <name>ICanController</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.automotive.evs</name>
<version>1.0</version>
<interface>
@@ -249,6 +261,13 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.identity</name>
+ <interface>
+ <name>IIdentityCredentialStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.ir</name>
<version>1.0</version>
diff --git a/compatibility_matrices/compatibility_matrix.legacy.xml b/compatibility_matrices/compatibility_matrix.legacy.xml
index 224811f..8a4d2ee 100644
--- a/compatibility_matrices/compatibility_matrix.legacy.xml
+++ b/compatibility_matrices/compatibility_matrix.legacy.xml
@@ -71,7 +71,7 @@
<instance>legacy/0</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
<name>android.hardware.configstore</name>
<version>1.0</version>
<interface>
diff --git a/configstore/1.1/default/Android.mk b/configstore/1.1/default/Android.mk
index e7edc34..6b7bb00 100644
--- a/configstore/1.1/default/Android.mk
+++ b/configstore/1.1/default/Android.mk
@@ -35,3 +35,14 @@
LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy
include $(BUILD_PREBUILT)
endif
+
+# disable configstore
+include $(CLEAR_VARS)
+LOCAL_MODULE := disable_configstore
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES:= disable_configstore.cpp
+LOCAL_OVERRIDES_MODULES := android.hardware.configstore@1.1-service
+LOCAL_VENDOR_MODULE := true
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_EXECUTABLE)
diff --git a/configstore/1.1/default/disable_configstore.cpp b/configstore/1.1/default/disable_configstore.cpp
new file mode 100644
index 0000000..b727ddb
--- /dev/null
+++ b/configstore/1.1/default/disable_configstore.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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.
+ */
+
+int main() {
+ return 1;
+}
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index fd088cd..c8b522c 100644
--- a/confirmationui/1.0/vts/functional/Android.bp
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -27,5 +27,5 @@
"libcn-cbor",
"android.hardware.confirmationui-support-lib",
],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts-core"],
}
diff --git a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
index fb01ad0..d953ab0 100644
--- a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
+++ b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
@@ -26,8 +26,12 @@
#include <android/hardware/confirmationui/1.0/types.h>
#include <android/hardware/confirmationui/support/confirmationui_utils.h>
+#include <gtest/gtest.h>
+
#include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
+
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
@@ -199,43 +203,18 @@
}
};
-class ConfirmationUIHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static ConfirmationUIHidlEnvironment* Instance() {
- static ConfirmationUIHidlEnvironment* instance = new ConfirmationUIHidlEnvironment;
- return instance;
- }
-
- void registerTestServices() override { registerTestService<IConfirmationUI>(); }
-
- private:
- ConfirmationUIHidlEnvironment(){};
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ConfirmationUIHidlEnvironment);
-};
-
-class ConfirmationUIHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- public:
- void TearDown() override { confirmator().abort(); }
-
- static void SetUpTestCase() {
- string service_name =
- ConfirmationUIHidlEnvironment::Instance()->getServiceName<IConfirmationUI>();
- confirmator_ = IConfirmationUI::getService(service_name);
+class ConfirmationUIHidlTest : public ::testing::TestWithParam<std::string> {
+ public:
+ void TearDown() override { confirmator_->abort(); }
+ void SetUp() override {
+ confirmator_ = IConfirmationUI::getService(GetParam());
ASSERT_NE(nullptr, confirmator_.get());
}
- static void TearDownTestCase() { confirmator_.clear(); }
-
- static IConfirmationUI& confirmator() { return *confirmator_; }
-
- private:
- static sp<IConfirmationUI> confirmator_;
+ protected:
+ sp<IConfirmationUI> confirmator_;
};
-sp<IConfirmationUI> ConfirmationUIHidlTest::confirmator_;
-
#define ASSERT_HAL_CALL(expected, call) \
{ \
auto result = call; \
@@ -250,17 +229,17 @@
typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
// Simulates the User taping Ok
-TEST_F(ConfirmationUIHidlTest, UserOkTest) {
+TEST_P(ConfirmationUIHidlTest, UserOkTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
- makeTestToken(TestModeCommands::OK_EVENT)));
+ ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+ makeTestToken(TestModeCommands::OK_EVENT)));
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::OK, result.args->error_);
@@ -294,40 +273,40 @@
}
// Initiates a confirmation prompt with a message that is too long
-TEST_F(ConfirmationUIHidlTest, MessageTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageTooLongTest) {
static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX)] = {};
static constexpr char test_prompt[] = "D\'oh!";
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// If the message gets very long some HAL implementations might fail even before the message
// reaches the trusted app implementation. But the HAL must still diagnose the correct error.
-TEST_F(ConfirmationUIHidlTest, MessageWayTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageWayTooLongTest) {
static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX) * 10] = {};
static constexpr char test_prompt[] = "D\'oh!";
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Simulates the User tapping the Cancel
-TEST_F(ConfirmationUIHidlTest, UserCancelTest) {
+TEST_P(ConfirmationUIHidlTest, UserCancelTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
- makeTestToken(TestModeCommands::CANCEL_EVENT)));
+ ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+ makeTestToken(TestModeCommands::CANCEL_EVENT)));
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Canceled, result.args->error_);
@@ -337,16 +316,16 @@
}
// Simulates the framework cancelling an ongoing prompt
-TEST_F(ConfirmationUIHidlTest, AbortTest) {
+TEST_P(ConfirmationUIHidlTest, AbortTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -356,7 +335,7 @@
// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
// the design guidelines.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest1) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
"WWWWWWWWWWWWWW";
@@ -365,9 +344,9 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -377,7 +356,7 @@
// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
// the design guidelines in magnified mode.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest1Magnified) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1Magnified) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
"WWWWWWWWWWWWWW";
@@ -386,10 +365,10 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
{UIOption::AccessibilityMagnified}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -399,7 +378,7 @@
// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
// required by the design guidelines.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest2) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
"WWWWWWWWWWWW WWWWWWWWWWWW";
@@ -408,9 +387,9 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -420,7 +399,7 @@
// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
// required by the design guidelines in magnified mode.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest2Magnified) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2Magnified) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
"WWWWWWWWWWWW WWWWWWWWWWWW";
@@ -429,10 +408,10 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
{UIOption::AccessibilityMagnified}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -442,19 +421,19 @@
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string that ends in the middle of a multibyte character
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test1) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test1) {
static constexpr char test_prompt[] = {char(0xc0), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string with a 5-byte character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test2) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test2) {
static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
char(0x82), char(0x82), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
@@ -462,19 +441,19 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test3) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test3) {
static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Test the implementation of HMAC SHA 256 against a golden blob.
@@ -494,16 +473,13 @@
ASSERT_EQ(expected, result.value());
}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, ConfirmationUIHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IConfirmationUI::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
} // namespace test
} // namespace V1_0
} // namespace confirmationui
} // namespace hardware
} // namespace android
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- std::vector<std::string> positional_args;
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
-}
diff --git a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
index b659be8..fc2893f 100644
--- a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
+++ b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
@@ -1,5 +1,5 @@
service vendor.contexthub-hal-1-0 /vendor/bin/hw/android.hardware.contexthub@1.0-service
interface android.hardware.contexthub@1.0::IContexthub default
class hal
- user system
- group system
+ user context_hub
+ group context_hub
diff --git a/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc b/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
index 9db00f9..b00b1bd 100644
--- a/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
+++ b/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
@@ -2,5 +2,5 @@
interface android.hardware.contexthub@1.0::IContexthub default
interface android.hardware.contexthub@1.1::IContexthub default
class hal
- user system
- group system
+ user context_hub
+ group context_hub
diff --git a/current.txt b/current.txt
index 8e2016d..5d862d8 100644
--- a/current.txt
+++ b/current.txt
@@ -589,6 +589,7 @@
a05277065c28ebecd58118bd240fb8c55757361e8648c01f7c4dacdb7f2a95dc android.hardware.camera.metadata@3.3::types
9cb3df2bde2c6cd5fd96b7c41555420cacd7e276a556c684af91b7461c86460f android.hardware.gnss@1.0::IGnssCallback
af334f1fc85c62b343f84b74d0495eed6f495f7fecedb53463db10c202310058 android.hardware.gnss.measurement_corrections@1.0::types
+33a6b20c43af00fdfb305df891bc5911c06d9a9130b912759649932e5a4a6e6d android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControlCallback
bceee81ec1b59324abd05932b5620fda5a6589597c9cb3953ba7f3ea02cccd3e android.hardware.camera.provider@2.4::ICameraProvider
2ce820dc4f3c6d85721b65150ed2157c6e2e2055f866fb6c6ba4790f14408d66 android.hardware.camera.provider@2.4::ICameraProviderCallback
b69a7615c508acf5c5201efd1bfa3262167874fc3594e2db5a3ff93addd8ac75 android.hardware.keymaster@4.0::IKeymasterDevice
@@ -605,7 +606,6 @@
5751f230e86a36111e7c5b995577cbf89d8df76c8e6c7641199198f3db3a93f7 android.hardware.wifi@1.3::IWifiStaIface
# HALs released in Android R
-822369cf4dc16a6f6b9622bcf86cbdc0b692dc82193fc15e967767175cbfdd8f android.hardware.audio@6.0::types
7241bd4596a927cd46d4b82f5e29e2cbe57f194aa1b25555f1d1d352e8b15c61 android.hardware.audio@6.0::IDevice
2402876cbc23c0de3690a665eca84fd3857d1808dba5cad25ce272f81ecef8c9 android.hardware.audio@6.0::IDevicesFactory
bca5379d5065e2e08b6ad7308ffc8a71a972fc0698bec678ea32eea786d01cb5 android.hardware.audio@6.0::IPrimaryDevice
@@ -614,8 +614,8 @@
164826a380f4c1700183003f62d7532e367b67381c30ea44f946c0cf00008f85 android.hardware.audio@6.0::IStreamOut
997fdaad7a9d17ee7e01feb7031a753e2365e72ad30b11d950e9183fabdf3844 android.hardware.audio@6.0::IStreamOutCallback
e7ca0db9a1098210f327a9b152fa6afe6bf019c41e5264c64829d04d50c0a526 android.hardware.audio@6.0::IStreamOutEventCallback
+822369cf4dc16a6f6b9622bcf86cbdc0b692dc82193fc15e967767175cbfdd8f android.hardware.audio@6.0::types
bee662c62d997d8065e2bcb5c1e7a9578931f22ce28fd02c219fdb4d0630abf7 android.hardware.audio.common@6.0::types
-817930d58412d662cb45e641c50cb62c727e4a3e3ffe7029a53cad9677b97d58 android.hardware.audio.effect@6.0::types
525bec6b44f1103869c269a128d51b8dccd73af5340ba863c8886c68357c7faf android.hardware.audio.effect@6.0::IAcousticEchoCancelerEffect
8d76bbe3719d051a8e9a1dcf9244f37f5b0a491feb249fa48391edf7cb4f3131 android.hardware.audio.effect@6.0::IAutomaticGainControlEffect
461b1114cb35d89f87e5694e0792ba53c112a7fa9a14d9b95188cf9c4764be23 android.hardware.audio.effect@6.0::IBassBoostEffect
@@ -630,18 +630,19 @@
5237c42d3913ef569f07bec802568084b615155d05a7951e75085da54856508c android.hardware.audio.effect@6.0::IPresetReverbEffect
282193799d60bff27a84c65a36218c1e7d8f582f5828e2e059383d1b90aa56bd android.hardware.audio.effect@6.0::IVirtualizerEffect
0868e00f7c5ee16723bda1a8f57099763d04100ae7126a1c2d3a9a87c844a7e8 android.hardware.audio.effect@6.0::IVisualizerEffect
+817930d58412d662cb45e641c50cb62c727e4a3e3ffe7029a53cad9677b97d58 android.hardware.audio.effect@6.0::types
7e8e1c3d0173c5d503dd01cecff8e3864478557ca6b9e8cc2291598b1a4aea62 android.hardware.biometrics.face@1.1::IBiometricsFace
-ae6315fd42196478ac08441cb489d854118001bca5b9b9fd58af5110952be30e android.hardware.biometrics.fingerprint@2.2::types
6828bbf18dc5d0f00c73341a10c8e4d574346c1abb1c2ed682ba5e9f8a3240d9 android.hardware.biometrics.fingerprint@2.2::IBiometricsFingerprint
82cad99f5feb2ea9bcd4579055edf4af8feb9fc602a6e4827ddd727d254d4991 android.hardware.biometrics.fingerprint@2.2::IBiometricsFingerprintClientCallback
-79e115c8f8970b8b914bafc66df5425e065fda4dcda97222966ef12451d2a1cc android.hardware.bluetooth@1.1::IBluetoothHci
+ae6315fd42196478ac08441cb489d854118001bca5b9b9fd58af5110952be30e android.hardware.biometrics.fingerprint@2.2::types
+362fd1c21641c2224f3b80c30d9797b988fa3f344243d531ba73c553779a5763 android.hardware.bluetooth@1.1::IBluetoothHci
40ab2c6866c18d32baf6e49e3053949e79601f56963a791e93e68b9ee18f718d android.hardware.bluetooth@1.1::IBluetoothHciCallbacks
07d0a252b2d8fa35887908a996ba395cf392968395fc30afab791f46e0c22a52 android.hardware.boot@1.1::IBootControl
74049a402be913963edfdd80828a53736570e9d8124a1bf18166b6ed46a6b0ab android.hardware.boot@1.1::types
b8c63679e1a3874b356f3e691aecce1191d38f59063cf2ed2dce8a9d4cabf00e android.hardware.camera.device@3.6::ICameraDevice
-daad72a2f482d8a1f660d0e99ac1b78fedb414a4cfbe3fa56b2cd480e5d6f0cb android.hardware.camera.provider@2.6::ICameraProvider
-8f8d9463508ff9cae88eb35c429fd0e2dbca0ca8f5de7fdf836cc0c4370becb6 android.hardware.camera.provider@2.6::ICameraProviderCallback
a35d5151b48505f06a775b38c0e2e265f80a845d92802324c643565807f81c53 android.hardware.camera.device@3.6::types
+99aae72ae75a8ddf63ccffbc585f3a55f4d0847b4adff3d7a0f8bd9e2305bec1 android.hardware.camera.provider@2.6::ICameraProvider
+8f8d9463508ff9cae88eb35c429fd0e2dbca0ca8f5de7fdf836cc0c4370becb6 android.hardware.camera.provider@2.6::ICameraProviderCallback
c1aa508d00b66ed5feefea398fd5edf28fa651ac89773adad7dfda4e0a73a952 android.hardware.cas@1.2::ICas
9811f867def49b420d8c707f7e38d3bdd64f835244e1d2a5e9762ab9835672dc android.hardware.cas@1.2::ICasListener
f18695dd36ee205640b8326a17453858a7b4596653aaa6ef0016b0aef1bd4dac android.hardware.cas@1.2::IMediaCasService
@@ -650,25 +651,21 @@
3581d0ba61663cdd45807494dcd697d01c074f27587df9140655f94346969cfe android.hardware.contexthub@1.1::types
66931c2506fbb5af61f20138cb05e0a09e7bf67d6964c231d27c648933bb33ec android.hardware.drm@1.3::ICryptoFactory
994d08ab27d613022c258a9ec48cece7adf2a305e92df5d76ef923e2c6665f64 android.hardware.drm@1.3::IDrmFactory
-d9df99be0f59d8f33a9699fe316c67bfd11818aa69440bb1123ba43e717cea85 android.hardware.dumpstate@1.1::types
186bc152ae189ab48f3a761a44ddf5edd0d483073c5b6ca1f802f8b50488b754 android.hardware.dumpstate@1.1::IDumpstateDevice
-769d346927a94fd40ee80a5a976d8d15cf022ef99c5900738f4a82f26c0ed229 android.hardware.gnss@2.1::types
+d9df99be0f59d8f33a9699fe316c67bfd11818aa69440bb1123ba43e717cea85 android.hardware.dumpstate@1.1::types
c319e68b03829958404402c2d9c682019678087d60495807c0a7444e0a6af981 android.hardware.gnss@2.1::IGnss
ba5ac712b2a656dc07c83ab4a7a2c2f3bee1bbcb752e8b8ffa9b672f3b5b0728 android.hardware.gnss@2.1::IGnssAntennaInfo
0bc3ed97cbc3f6abc89c68f4e9f4d124f9f723431997dc88c2186cf4d2ad47ee android.hardware.gnss@2.1::IGnssAntennaInfoCallback
3541d83adfeac16ee3e45d183a58dffe06012ccb5aa5bcd2e4f6eeae269f69cd android.hardware.gnss@2.1::IGnssCallback
737d750017738f0753d13ba01a3310e0161f294b8ae80b3fd63eaa227e9d9c66 android.hardware.gnss@2.1::IGnssConfiguration
7913a11206a577b12ade86a7cf3f95c2639cb514d086673f279bf99238c9917e android.hardware.gnss@2.1::IGnssMeasurement
-0a16e5913e94d995cfcf959a1c6f10b0b8e9dfdb5f45ac6e7244711ddd740272 android.hardware.gnss@2.1::IGnssMeasurementCallback
+df52e2c39ed701a355b5e0fdbf83fe5fa7d04bfecd715116b39373d46dc3c682 android.hardware.gnss@2.1::IGnssMeasurementCallback
+769d346927a94fd40ee80a5a976d8d15cf022ef99c5900738f4a82f26c0ed229 android.hardware.gnss@2.1::types
6670e7780803a8c696c6391fda5589a334b1b37dc7be9393792ed35035413633 android.hardware.gnss.measurement_corrections@1.1::IMeasurementCorrections
956c1576ca0d6f11b42980ef59052062836b6763fe973af6cb709da50787f710 android.hardware.gnss.measurement_corrections@1.1::types
ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
26f04510a0b57aba5167c5c0a7c2f077c2acbb98b81902a072517829fd9fd67f android.hardware.health@2.1::IHealthInfoCallback
e2f8bc1868fd4a3fd587c172773ea5a8c2f5a3deaf7958394102ca455252b255 android.hardware.health@2.1::types
-0589e410f519e36514e7ece18f283f022df0f70efd2c12821d822f67f74aba98 android.hardware.identity@1.0::types
-bbeee9604128ede83ee755b67e73b5ad29e6e1dbac9ec41fea6ffe2745b0c50a android.hardware.identity@1.0::IIdentityCredential
-96ce8aad80f4c476f25261f790d357c117e79e18474c7dadd850dac704bbe65e android.hardware.identity@1.0::IIdentityCredentialStore
-8da9c938e58f7d636ddd2f92c646f99d9a9e79612e6441b6380ab12744251873 android.hardware.identity@1.0::IWritableIdentityCredential
27ae3724053940462114228872b3ffaf0b8e6177d5ba97f5a76339d12b8a99dd android.hardware.keymaster@4.1::IKeymasterDevice
adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
ddcf89cd8ee2df0d32aee55050826446fb64f7aafde0a7cd946c64f61b1a364c android.hardware.keymaster@4.1::types
@@ -680,8 +677,16 @@
6e904be0ddca5ae1de8eba020e6c38ed935ea7d80cd08f47787f137a0ca58555 android.hardware.neuralnetworks@1.3::IFencedExecutionCallback
2b0b10d2ea7a18a4048cd0eb83d35c19a817aeee95f65807fc31f4ef21381397 android.hardware.neuralnetworks@1.3::IPreparedModel
eee3430cc86c97c7b407495863d8fb61da6f1a64b7721e77b9b4909b11b174e9 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
-c9320b04ec302624985180a02d591bea5e435601fc411a6cabb58878e4e1ad68 android.hardware.neuralnetworks@1.3::types
-b335c3c732c799b299fa61c6de6260ab4d20cbd0ec21acd6db14d8156c745d0b android.hardware.tv.tuner@1.0::types
+e442ab1b440327fe4e8a3b0b8ac6874e9bc6342e91fe976eb9fea77c63961ec8 android.hardware.neuralnetworks@1.3::types
+b454df853441c12f6e425e8a60dd29fda20f5e6e39b93d1103e4b37495db38aa android.hardware.radio@1.5::IRadio
+fcbb0742a88215ee7a6d7ce0825d253eb2b50391fc6c8c48667f9fd7f6d4549e android.hardware.radio@1.5::IRadioIndication
+b809193970a91ca637a4b0184767315601d32e3ef3d5992ffbc7a8d14a14f015 android.hardware.radio@1.5::IRadioResponse
+e7669bddacbdaee2cd9a87762a13fb7648639eead54bf4d767dc06eaaeb35736 android.hardware.radio@1.5::types
+3ca6616381080bdd6c08141ad12775a94ae868c58b02b1274ae3326f7de724ab android.hardware.sensors@2.1::ISensors
+3d4141c6373cd9ca02fe221a7d12343840de2255d032c38248fe8e35816b58b2 android.hardware.sensors@2.1::ISensorsCallback
+8051cc50fc90ed447f058a8b15d81f35a65f1bd9004b1de4f127edeb89b47978 android.hardware.sensors@2.1::types
+b37f78e3fdc79af8b32a545b2b426f1fd1355b359d9e7835f3bf1ed0aa4518d8 android.hardware.soundtrigger@2.3::ISoundTriggerHw
+4a6517ea4ad807855428b0101d8e1a486497bd88ab4300ba3b2be43d46d32580 android.hardware.soundtrigger@2.3::types
adab52e647d1a1ccfbdabdfc9c73352f8e834b61322e505bc6e3d3a0d3acc259 android.hardware.tv.tuner@1.0::IDemux
548e1a16fc4f779346e14968a63cd6f160e1e2c8b8c99256b2bac24a24b52a9a android.hardware.tv.tuner@1.0::IDescrambler
b84597d59f0f1d03c9997d60eb15280f3950c287d46016240d89859789db4d47 android.hardware.tv.tuner@1.0::IDvr
@@ -694,6 +699,8 @@
b2310785bdb55f97bbbb2176e2ee73ed8d2a7ce5895bd20c997b90c5f2868ad8 android.hardware.tv.tuner@1.0::ILnbCallback
4788787e662293d526ff7789fc24e82533e7f6ff99a967ebc3e3ec6b17628796 android.hardware.tv.tuner@1.0::ITimeFilter
c350c7783843e0c7cf30f90c918770b0d3c09fc0fe5e532e2f2e7210fcfe71c9 android.hardware.tv.tuner@1.0::ITuner
+b335c3c732c799b299fa61c6de6260ab4d20cbd0ec21acd6db14d8156c745d0b android.hardware.tv.tuner@1.0::types
+7746fda1fbf9c7c132bae701cc5a161309e4f5e7f3e8065811045975ee86196d android.hardware.usb.gadget@1.1::IUsbGadget
3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b android.hardware.wifi@1.4::IWifi
c67aaf26a7a40d14ea61e70e20afacbd0bb906df1704d585ac8599fbb69dd44b android.hardware.wifi.hostapd@1.2::IHostapd
2b5a7ea572b736030c64a3b4043af244425477c4672301780fe15aba5ed393d9 android.hardware.wifi.hostapd@1.2::types
@@ -702,13 +709,3 @@
2ce1f7fb52e49f80b13a9b153d491bce530552f02357ea729acae922a8659f93 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
77531c8d048f8f8ae532babd0ca86332a865ec9aace1b051226ef2b21123e645 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
-99f5c26b952271d1246c957e1d0271fa39445ee65cc93aa7c187834f98914a33 android.hardware.radio@1.5::types
-890ecacaaa6660802bac01bbbe5f16b1eb1d6a3a3f0e5b398be5cec76a5ab673 android.hardware.radio@1.5::IRadio
-e96ae1c3a9c0689002ec2318e9c587f4f607c16a75a3cd38788b77eb91072021 android.hardware.radio@1.5::IRadioIndication
-829d3827eeb5a8f563e80fe627419b3231012fc02bc2e79782ec5e9ad9f799a4 android.hardware.radio@1.5::IRadioResponse
-3ca6616381080bdd6c08141ad12775a94ae868c58b02b1274ae3326f7de724ab android.hardware.sensors@2.1::ISensors
-3d4141c6373cd9ca02fe221a7d12343840de2255d032c38248fe8e35816b58b2 android.hardware.sensors@2.1::ISensorsCallback
-8051cc50fc90ed447f058a8b15d81f35a65f1bd9004b1de4f127edeb89b47978 android.hardware.sensors@2.1::types
-4a6517ea4ad807855428b0101d8e1a486497bd88ab4300ba3b2be43d46d32580 android.hardware.soundtrigger@2.3::types
-b37f78e3fdc79af8b32a545b2b426f1fd1355b359d9e7835f3bf1ed0aa4518d8 android.hardware.soundtrigger@2.3::ISoundTriggerHw
-7746fda1fbf9c7c132bae701cc5a161309e4f5e7f3e8065811045975ee86196d android.hardware.usb.gadget@1.1::IUsbGadget
diff --git a/drm/1.3/vts/functional/Android.bp b/drm/1.3/vts/functional/Android.bp
index 4be1575..ac1f912 100644
--- a/drm/1.3/vts/functional/Android.bp
+++ b/drm/1.3/vts/functional/Android.bp
@@ -30,12 +30,12 @@
"android.hardware.drm@1.3",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libcrypto",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
export_include_dirs: [
@@ -63,12 +63,12 @@
"android.hardware.drm@1.3",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libcrypto",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
test_suites: [
diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp
index d778d50..a3ea807 100644
--- a/gnss/2.0/default/GnssMeasurement.cpp
+++ b/gnss/2.0/default/GnssMeasurement.cpp
@@ -49,8 +49,8 @@
Return<void> GnssMeasurement::close() {
ALOGD("close");
- std::unique_lock<std::mutex> lock(mMutex);
stop();
+ std::unique_lock<std::mutex> lock(mMutex);
sCallback = nullptr;
return Void();
}
diff --git a/gnss/2.0/default/GnssMeasurement.h b/gnss/2.0/default/GnssMeasurement.h
index d8ffd59..73eaa13 100644
--- a/gnss/2.0/default/GnssMeasurement.h
+++ b/gnss/2.0/default/GnssMeasurement.h
@@ -61,10 +61,14 @@
void stop();
void reportMeasurement(const GnssData&);
+ // Guarded by mMutex
static sp<IGnssMeasurementCallback> sCallback;
+
std::atomic<long> mMinIntervalMillis;
std::atomic<bool> mIsActive;
std::thread mThread;
+
+ // Synchronization lock for sCallback
mutable std::mutex mMutex;
};
diff --git a/gnss/2.1/IGnssMeasurementCallback.hal b/gnss/2.1/IGnssMeasurementCallback.hal
index 0e6abbd..60a5423 100644
--- a/gnss/2.1/IGnssMeasurementCallback.hal
+++ b/gnss/2.1/IGnssMeasurementCallback.hal
@@ -30,13 +30,13 @@
*/
enum GnssMeasurementFlags : @1.0::IGnssMeasurementCallback.GnssMeasurementFlags {
/**
- * A valid receiver inter-signal bias is stored in the data structure.
+ * A valid full inter-signal bias is stored in the data structure.
*/
- HAS_RECEIVER_ISB = 1 << 16,
+ HAS_FULL_ISB = 1 << 16,
/**
- * A valid receiver inter-signal bias uncertainty is stored in the data structure.
+ * A valid full inter-signal bias uncertainty is stored in the data structure.
*/
- HAS_RECEIVER_ISB_UNCERTAINTY = 1 << 17,
+ HAS_FULL_ISB_UNCERTAINTY = 1 << 17,
/**
* A valid satellite inter-signal bias is stored in the data structure.
*/
@@ -77,42 +77,58 @@
bitfield<GnssMeasurementFlags> flags;
/**
- * The receiver inter-signal bias (ISB) in nanoseconds.
+ * The full inter-signal bias (ISB) in nanoseconds.
*
- * This value is the estimated receiver-side inter-system (different from the constellation
- * in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different from the
- * carrier frequency in GnssClock.referenceSignalTypeForIsb) bias. The reported receiver ISB
- * must include signal delays caused by
+ * This value is the sum of the estimated receiver-side and the space-segment-side
+ * inter-system bias, inter-frequency bias and inter-code bias, including
*
- * - Receiver inter-constellation bias
- * - Receiver inter-frequency bias
- * - Receiver inter-code bias
+ * - Receiver inter-constellation bias (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-frequency bias (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Receiver inter-code bias (with respect to the code type in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+ * (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Group delay (e.g., Total Group Delay (TGD))
+ * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+ * code type in GnssClock.referenceSignalTypeForIsb)
+ *
+ * If a component of the above is already compensated in the provided
+ * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full
+ * ISB.
*
* The value does not include the inter-frequency Ionospheric bias.
*
- * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
*/
- double receiverInterSignalBiasNs;
+ double fullInterSignalBiasNs;
/**
- * 1-sigma uncertainty associated with the receiver inter-signal bias in nanoseconds.
+ * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds.
*/
- double receiverInterSignalBiasUncertaintyNs;
+ double fullInterSignalBiasUncertaintyNs;
/**
* The satellite inter-signal bias in nanoseconds.
*
- * This value is the satellite-and-control-segment-side inter-system (different from the
- * constellation in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different
- * from the carrier frequency in GnssClock.referenceSignalTypeForIsb) bias, including:
+ * This value is the sum of the space-segment-side inter-system bias, inter-frequency bias
+ * and inter-code bias, including
*
- * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
- * BDS-GLO Time Offset (BGTO))
+ * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+ * (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+ * GnssClock.referenceSignalTypeForIsb)
* - Group delay (e.g., Total Group Delay (TGD))
- * - Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
- * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).
+ * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * GnssClock.referenceSignalTypeForIsb)
+ * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+ * code type in GnssClock.referenceSignalTypeForIsb)
*
- * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+ * The satellite ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0
+ * nanoseconds.
*/
double satelliteInterSignalBiasNs;
diff --git a/gnss/2.1/default/GnssAntennaInfo.cpp b/gnss/2.1/default/GnssAntennaInfo.cpp
index d32a0af..ed183a9 100644
--- a/gnss/2.1/default/GnssAntennaInfo.cpp
+++ b/gnss/2.1/default/GnssAntennaInfo.cpp
@@ -55,8 +55,8 @@
Return<void> GnssAntennaInfo::close() {
ALOGD("close");
- std::unique_lock<std::mutex> lock(mMutex);
stop();
+ std::unique_lock<std::mutex> lock(mMutex);
sCallback = nullptr;
return Void();
}
diff --git a/gnss/2.1/default/GnssAntennaInfo.h b/gnss/2.1/default/GnssAntennaInfo.h
index f4bfd24..94b2111 100644
--- a/gnss/2.1/default/GnssAntennaInfo.h
+++ b/gnss/2.1/default/GnssAntennaInfo.h
@@ -47,10 +47,14 @@
void reportAntennaInfo(
const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const;
+ // Guarded by mMutex
static sp<IGnssAntennaInfoCallback> sCallback;
+
std::atomic<long> mMinIntervalMillis;
std::atomic<bool> mIsActive;
std::thread mThread;
+
+ // Synchronization lock for sCallback
mutable std::mutex mMutex;
};
@@ -60,4 +64,4 @@
} // namespace hardware
} // namespace android
-#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
\ No newline at end of file
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
diff --git a/gnss/2.1/default/GnssMeasurement.cpp b/gnss/2.1/default/GnssMeasurement.cpp
index 34e20e5..63bbc0a 100644
--- a/gnss/2.1/default/GnssMeasurement.cpp
+++ b/gnss/2.1/default/GnssMeasurement.cpp
@@ -47,8 +47,8 @@
Return<void> GnssMeasurement::close() {
ALOGD("close");
- std::unique_lock<std::mutex> lock(mMutex);
stop();
+ std::unique_lock<std::mutex> lock(mMutex);
sCallback_2_1 = nullptr;
sCallback_2_0 = nullptr;
return Void();
diff --git a/gnss/2.1/default/GnssMeasurement.h b/gnss/2.1/default/GnssMeasurement.h
index 3ed7bc5..d446419 100644
--- a/gnss/2.1/default/GnssMeasurement.h
+++ b/gnss/2.1/default/GnssMeasurement.h
@@ -66,11 +66,17 @@
void reportMeasurement(const GnssDataV2_0&);
void reportMeasurement(const GnssDataV2_1&);
+ // Guarded by mMutex
static sp<V2_1::IGnssMeasurementCallback> sCallback_2_1;
+
+ // Guarded by mMutex
static sp<V2_0::IGnssMeasurementCallback> sCallback_2_0;
+
std::atomic<long> mMinIntervalMillis;
std::atomic<bool> mIsActive;
std::thread mThread;
+
+ // Synchronization lock for sCallback_2_1 and sCallback_2_0
mutable std::mutex mMutex;
};
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
index 7b054c0..33feb5e 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -98,7 +98,7 @@
* TestGnssMeasurementFields:
* Sets a GnssMeasurementCallback, waits for a measurement, and verifies
* 1. basebandCN0DbHz is valid
- * 2. ISB fields are valid if HAS_INTER_SIGNAL_BIAS is true.
+ * 2. ISB fields are valid
*/
TEST_P(GnssHalTest, TestGnssMeasurementFields) {
const int kFirstGnssMeasurementTimeoutSeconds = 10;
@@ -126,9 +126,8 @@
// Verify basebandCn0DbHz is valid.
ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0);
- if (((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_RECEIVER_ISB) > 0) &&
- ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_RECEIVER_ISB_UNCERTAINTY) >
- 0) &&
+ if (((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_FULL_ISB) > 0) &&
+ ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) > 0) &&
((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) > 0) &&
((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) >
0)) {
@@ -143,8 +142,8 @@
ASSERT_TRUE(carrierFrequencyHz > 0);
ASSERT_TRUE(codeType != "");
- ASSERT_TRUE(std::abs(measurement.receiverInterSignalBiasNs) < 1.0e6);
- ASSERT_TRUE(measurement.receiverInterSignalBiasUncertaintyNs >= 0);
+ ASSERT_TRUE(std::abs(measurement.fullInterSignalBiasNs) < 1.0e6);
+ ASSERT_TRUE(measurement.fullInterSignalBiasUncertaintyNs >= 0);
ASSERT_TRUE(std::abs(measurement.satelliteInterSignalBiasNs) < 1.0e6);
ASSERT_TRUE(measurement.satelliteInterSignalBiasUncertaintyNs >= 0);
}
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 2e5b873..386090e 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -39,12 +39,12 @@
.v2_0 = gnssDataV2_0.measurements[0],
.flags = (uint32_t)(GnssMeasurementFlagsV2_1::HAS_CARRIER_FREQUENCY |
GnssMeasurementFlagsV2_1::HAS_CARRIER_PHASE |
- GnssMeasurementFlagsV2_1::HAS_RECEIVER_ISB |
- GnssMeasurementFlagsV2_1::HAS_RECEIVER_ISB_UNCERTAINTY |
+ GnssMeasurementFlagsV2_1::HAS_FULL_ISB |
+ GnssMeasurementFlagsV2_1::HAS_FULL_ISB_UNCERTAINTY |
GnssMeasurementFlagsV2_1::HAS_SATELLITE_ISB |
GnssMeasurementFlagsV2_1::HAS_SATELLITE_ISB_UNCERTAINTY),
- .receiverInterSignalBiasNs = 10.0,
- .receiverInterSignalBiasUncertaintyNs = 100.0,
+ .fullInterSignalBiasNs = 30.0,
+ .fullInterSignalBiasUncertaintyNs = 250.0,
.satelliteInterSignalBiasNs = 20.0,
.satelliteInterSignalBiasUncertaintyNs = 150.0,
.basebandCN0DbHz = 25.0,
diff --git a/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal b/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal
index 5a582c2..5ee2923 100644
--- a/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal
+++ b/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal
@@ -82,6 +82,9 @@
/**
* Package name of the Android proxy application representing the non-framework
* entity that requested location. Set to empty string if unknown.
+ *
+ * For user-initiated emergency use cases, this field must be set to empty string
+ * and the inEmergencyMode field must be set to true.
*/
string proxyAppPackageName;
@@ -157,4 +160,4 @@
* @return success True if the framework determines that the device is in emergency session.
*/
isInEmergencySession() generates (bool success);
-};
\ No newline at end of file
+};
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
index 4942462..4e0c5ef 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
@@ -403,10 +403,6 @@
* cr_offset = y_size
* cb_offset = y_size + c_size
*
- * This range is reserved for vendor extensions. Formats in this range
- * must support BufferUsage::GPU_TEXTURE. Clients must assume they do not
- * have an alpha component.
- *
* This format must be accepted by the allocator when used with the
* following usage flags:
*
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponent.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponent.aidl
index 3fca53b..c04cef0 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponent.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponent.aidl
@@ -39,7 +39,7 @@
/**
* The type of this plane layout component.
*
- * android.hardware.graphics.common.PlaneLayoutComponent defines the standard
+ * android.hardware.graphics.common.PlaneLayoutComponentType defines the standard
* plane layout component types. Vendors may extend this type to include any
* non-standard plane layout component types. For instructions on how to
* create a vendor extension, refer to ExtendableType.aidl.
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 1185945..3d792f9 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -94,7 +94,7 @@
mDummyDescriptorInfo.width);
ASSERT_EQ(Error::BAD_BUFFER, ret)
<< "validateBufferSize with raw buffer handle did not fail with BAD_BUFFER";
- native_handle_delete(rawBufferHandle);
+ ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawBufferHandle));
}
/**
@@ -179,11 +179,11 @@
ASSERT_NO_FATAL_FAILURE(rawBufferHandle = const_cast<native_handle_t*>(
mGralloc->allocate(mDummyDescriptorInfo, false)));
mGralloc->getMapper()->getTransportSize(
- invalidHandle, [&](const auto& tmpError, const auto&, const auto&) {
- ASSERT_EQ(Error::BAD_BUFFER, tmpError)
- << "getTransportSize with raw buffer handle did not fail with BAD_BUFFER";
- });
- native_handle_delete(rawBufferHandle);
+ rawBufferHandle, [&](const auto& tmpError, const auto&, const auto&) {
+ ASSERT_EQ(Error::BAD_BUFFER, tmpError)
+ << "getTransportSize with raw buffer handle did not fail with BAD_BUFFER";
+ });
+ ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawBufferHandle));
}
/**
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 295ba36..a783eaa 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -221,7 +221,7 @@
case PlaneLayoutComponentType::Y:
ASSERT_EQ(nullptr, outYCbCr->y);
ASSERT_EQ(8, planeLayoutComponent.sizeInBits);
- ASSERT_EQ(8, planeLayout.sampleIncrementInBits);
+ ASSERT_EQ(32, planeLayout.sampleIncrementInBits);
outYCbCr->y = tmpData;
outYCbCr->ystride = planeLayout.strideInBytes;
break;
@@ -2124,8 +2124,14 @@
Error err;
mGralloc->getAllocator()->allocate(
- descriptor, 1,
- [&](const auto& tmpError, const auto&, const auto&) { err = tmpError; });
+ descriptor, 1, [&](const auto& tmpError, const auto&, const auto& tmpBuffers) {
+ err = tmpError;
+ if (err == Error::NONE) {
+ ASSERT_EQ(1, tmpBuffers.size());
+ ASSERT_NO_FATAL_FAILURE(bufferHandle =
+ mGralloc->importBuffer(tmpBuffers[0]));
+ }
+ });
if (err == Error::UNSUPPORTED) {
continue;
}
diff --git a/health/2.0/default/HealthImplDefault.cpp b/health/2.0/default/HealthImplDefault.cpp
index e3cbefd..08fee9e 100644
--- a/health/2.0/default/HealthImplDefault.cpp
+++ b/health/2.0/default/HealthImplDefault.cpp
@@ -21,18 +21,6 @@
using android::hardware::health::V2_0::implementation::Health;
static struct healthd_config gHealthdConfig = {
- .batteryStatusPath = android::String8(android::String8::kEmptyString),
- .batteryHealthPath = android::String8(android::String8::kEmptyString),
- .batteryPresentPath = android::String8(android::String8::kEmptyString),
- .batteryCapacityPath = android::String8(android::String8::kEmptyString),
- .batteryVoltagePath = android::String8(android::String8::kEmptyString),
- .batteryTemperaturePath = android::String8(android::String8::kEmptyString),
- .batteryTechnologyPath = android::String8(android::String8::kEmptyString),
- .batteryCurrentNowPath = android::String8(android::String8::kEmptyString),
- .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString),
- .batteryChargeCounterPath = android::String8(android::String8::kEmptyString),
- .batteryFullChargePath = android::String8(android::String8::kEmptyString),
- .batteryCycleCountPath = android::String8(android::String8::kEmptyString),
.energyCounter = nullptr,
.boot_min_cap = 0,
.screen_on = nullptr};
diff --git a/health/utils/libhealthloop/utils.cpp b/health/utils/libhealthloop/utils.cpp
index 053fd19..cd8c7a9 100644
--- a/health/utils/libhealthloop/utils.cpp
+++ b/health/utils/libhealthloop/utils.cpp
@@ -28,21 +28,6 @@
*healthd_config = {
.periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
.periodic_chores_interval_slow = DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW,
- .batteryStatusPath = String8(String8::kEmptyString),
- .batteryHealthPath = String8(String8::kEmptyString),
- .batteryPresentPath = String8(String8::kEmptyString),
- .batteryCapacityPath = String8(String8::kEmptyString),
- .batteryVoltagePath = String8(String8::kEmptyString),
- .batteryTemperaturePath = String8(String8::kEmptyString),
- .batteryTechnologyPath = String8(String8::kEmptyString),
- .batteryCurrentNowPath = String8(String8::kEmptyString),
- .batteryCurrentAvgPath = String8(String8::kEmptyString),
- .batteryChargeCounterPath = String8(String8::kEmptyString),
- .batteryFullChargePath = String8(String8::kEmptyString),
- .batteryCycleCountPath = String8(String8::kEmptyString),
- .batteryCapacityLevelPath = String8(String8::kEmptyString),
- .batteryChargeTimeToFullNowPath = String8(String8::kEmptyString),
- .batteryFullChargeDesignCapacityUahPath = String8(String8::kEmptyString),
.energyCounter = NULL,
.boot_min_cap = 0,
.screen_on = NULL,
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 10ce4c2..cc14271 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -176,6 +176,10 @@
* @param itemsRequest
* If non-empty, contains request data that is signed by the reader. See above.
*
+ * @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
+ * below) containing the signing key to use to sign the data retrieved. If this
+ * is not in the right format the call fails with STATUS_INVALID_DATA.
+ *
* @param sessionTranscript
* Either empty or the CBOR of the SessionTranscript. See above.
*
@@ -195,8 +199,7 @@
* and remove the corresponding requests from the counts.
*/
void startRetrieval(in SecureAccessControlProfile[] accessControlProfiles,
- in HardwareAuthToken authToken,
- in byte[] itemsRequest,
+ in HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob,
in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
/**
@@ -254,10 +257,6 @@
* If signingKeyBlob or the sessionTranscript parameter passed to startRetrieval() is
* empty then the returned MAC will be empty.
*
- * @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
- * below) containing the signing key to use to sign the data retrieved. If this
- * is not in the right format the call fails with STATUS_INVALID_DATA.
- *
* @param out mac is empty if signingKeyBlob or the sessionTranscript passed to
* startRetrieval() is empty. Otherwise it is a COSE_Mac0 with empty payload
* and the detached content is set to DeviceAuthentication as defined below.
@@ -304,7 +303,7 @@
*
* @param out deviceNameSpaces the bytes of DeviceNameSpaces.
*/
- void finishRetrieval(in byte[] signingKeyBlob, out byte[] mac, out byte[] deviceNameSpaces);
+ void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
/**
* Generate a key pair to be used for signing session data and retrieved data items.
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index d5b3a0f..341fae6 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -256,8 +256,8 @@
ndk::ScopedAStatus IdentityCredential::startRetrieval(
const vector<SecureAccessControlProfile>& accessControlProfiles,
const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequestS,
- const vector<int8_t>& sessionTranscriptS, const vector<int8_t>& readerSignatureS,
- const vector<int32_t>& requestCounts) {
+ const vector<int8_t>& signingKeyBlobS, const vector<int8_t>& sessionTranscriptS,
+ const vector<int8_t>& readerSignatureS, const vector<int32_t>& requestCounts) {
auto sessionTranscript = byteStringToUnsigned(sessionTranscriptS);
auto itemsRequest = byteStringToUnsigned(itemsRequestS);
auto readerSignature = byteStringToUnsigned(readerSignatureS);
@@ -498,6 +498,7 @@
currentNameSpace_ = "";
itemsRequest_ = itemsRequest;
+ signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
numStartRetrievalCalls_ += 1;
return ndk::ScopedAStatus::ok();
@@ -650,11 +651,8 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus IdentityCredential::finishRetrieval(const vector<int8_t>& signingKeyBlobS,
- vector<int8_t>* outMac,
+ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
vector<int8_t>* outDeviceNameSpaces) {
- auto signingKeyBlob = byteStringToUnsigned(signingKeyBlobS);
-
if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
deviceNameSpacesMap_.add(currentNameSpace_,
std::move(currentNameSpaceDeviceNameSpacesMap_));
@@ -664,7 +662,8 @@
// If there's no signing key or no sessionTranscript or no reader ephemeral
// public key, we return the empty MAC.
optional<vector<uint8_t>> mac;
- if (signingKeyBlob.size() > 0 && sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0) {
+ if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
+ readerPublicKey_.size() > 0) {
cppbor::Array array;
array.add("DeviceAuthentication");
array.add(sessionTranscriptItem_->clone());
@@ -674,7 +673,7 @@
vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
optional<vector<uint8_t>> signingKey =
- support::decryptAes128Gcm(storageKey_, signingKeyBlob, docTypeAsBlob);
+ support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob);
if (!signingKey) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA,
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index 49ed0d4..fc29254 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -54,14 +54,14 @@
ndk::ScopedAStatus startRetrieval(
const vector<SecureAccessControlProfile>& accessControlProfiles,
const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequest,
- const vector<int8_t>& sessionTranscript, const vector<int8_t>& readerSignature,
- const vector<int32_t>& requestCounts) override;
+ const vector<int8_t>& signingKeyBlob, const vector<int8_t>& sessionTranscript,
+ const vector<int8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
ndk::ScopedAStatus startRetrieveEntryValue(
const string& nameSpace, const string& name, int32_t entrySize,
const vector<int32_t>& accessControlProfileIds) override;
ndk::ScopedAStatus retrieveEntryValue(const vector<int8_t>& encryptedContent,
vector<int8_t>* outContent) override;
- ndk::ScopedAStatus finishRetrieval(const vector<int8_t>& signingKeyBlob, vector<int8_t>* outMac,
+ ndk::ScopedAStatus finishRetrieval(vector<int8_t>* outMac,
vector<int8_t>* outDeviceNameSpaces) override;
ndk::ScopedAStatus generateSigningKeyPair(vector<int8_t>* outSigningKeyBlob,
Certificate* outSigningKeyCertificate) override;
@@ -88,6 +88,7 @@
// Set at startRetrieval() time.
map<int32_t, int> profileIdToAccessCheckResult_;
+ vector<uint8_t> signingKeyBlob_;
vector<uint8_t> sessionTranscript_;
std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
vector<uint8_t> itemsRequest_;
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index ba2062d..89f7f35 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -16,6 +16,9 @@
#define LOG_TAG "WritableIdentityCredential"
+#include "WritableIdentityCredential.h"
+#include "IdentityCredentialStore.h"
+
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
#include <android-base/logging.h>
@@ -23,6 +26,8 @@
#include <cppbor/cppbor.h>
#include <cppbor/cppbor_parse.h>
+#include <utility>
+
#include "IdentityCredentialStore.h"
#include "Util.h"
#include "WritableIdentityCredential.h"
@@ -33,26 +38,6 @@
using namespace ::android::hardware::identity;
bool WritableIdentityCredential::initialize() {
- optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
- if (!keyPair) {
- LOG(ERROR) << "Error creating credentialKey";
- return false;
- }
-
- optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
- if (!pubKey) {
- LOG(ERROR) << "Error getting public part of credentialKey";
- return false;
- }
- credentialPubKey_ = pubKey.value();
-
- optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
- if (!privKey) {
- LOG(ERROR) << "Error getting private part of credentialKey";
- return false;
- }
- credentialPrivKey_ = privKey.value();
-
optional<vector<uint8_t>> random = support::getRandom(16);
if (!random) {
LOG(ERROR) << "Error creating storageKey";
@@ -63,88 +48,54 @@
return true;
}
-// TODO: use |attestationApplicationId| and |attestationChallenge| and also
-// ensure the returned certificate chain satisfy the requirements listed in
-// the docs for IWritableIdentityCredential::getAttestationCertificate()
-//
+// This function generates the attestation certificate using the passed in
+// |attestationApplicationId| and |attestationChallenge|. It will generate an
+// attestation certificate with current time and expires one year from now. The
+// certificate shall contain all values as specified in hal.
ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate(
- const vector<int8_t>& /*attestationApplicationId*/,
- const vector<int8_t>& /*attestationChallenge*/, vector<Certificate>* outCertificateChain) {
- // For now, we dynamically generate an attestion key on each and every
- // request and use that to sign CredentialKey. In a real implementation this
- // would look very differently.
- optional<vector<uint8_t>> attestationKeyPair = support::createEcKeyPair();
- if (!attestationKeyPair) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_FAILED, "Error creating attestationKey"));
- }
-
- optional<vector<uint8_t>> attestationPubKey =
- support::ecKeyPairGetPublicKey(attestationKeyPair.value());
- if (!attestationPubKey) {
+ const vector<int8_t>& attestationApplicationId, //
+ const vector<int8_t>& attestationChallenge, //
+ vector<Certificate>* outCertificateChain) {
+ if (!credentialPrivKey_.empty() || !credentialPubKey_.empty() || !certificateChain_.empty()) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
- "Error getting public part of attestationKey"));
+ "Error attestation certificate previously generated"));
}
- optional<vector<uint8_t>> attestationPrivKey =
- support::ecKeyPairGetPrivateKey(attestationKeyPair.value());
- if (!attestationPrivKey) {
+ vector<uint8_t> challenge(attestationChallenge.begin(), attestationChallenge.end());
+ vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end());
+
+ optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> keyAttestationPair =
+ support::createEcKeyPairAndAttestation(challenge, appId);
+ if (!keyAttestationPair) {
+ LOG(ERROR) << "Error creating credentialKey and attestation";
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
- "Error getting private part of attestationKey"));
+ "Error creating credentialKey and attestation"));
}
- string serialDecimal;
- string issuer;
- string subject;
- time_t validityNotBefore = time(nullptr);
- time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
+ vector<uint8_t> keyPair = keyAttestationPair.value().first;
+ certificateChain_ = keyAttestationPair.value().second;
- // First create a certificate for |credentialPubKey| which is signed by
- // |attestationPrivKey|.
- //
- serialDecimal = "0"; // TODO: set serial to |attestationChallenge|
- issuer = "Android Open Source Project";
- subject = "Android IdentityCredential CredentialKey";
- optional<vector<uint8_t>> credentialPubKeyCertificate = support::ecPublicKeyGenerateCertificate(
- credentialPubKey_, attestationPrivKey.value(), serialDecimal, issuer, subject,
- validityNotBefore, validityNotAfter);
- if (!credentialPubKeyCertificate) {
+ optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair);
+ if (!pubKey) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
- "Error creating certificate for credentialPubKey"));
+ "Error getting public part of credentialKey"));
}
+ credentialPubKey_ = pubKey.value();
- // This is followed by a certificate for |attestationPubKey| self-signed by
- // |attestationPrivKey|.
- serialDecimal = "0"; // TODO: set serial
- issuer = "Android Open Source Project";
- subject = "Android IdentityCredential AttestationKey";
- optional<vector<uint8_t>> attestationKeyCertificate = support::ecPublicKeyGenerateCertificate(
- attestationPubKey.value(), attestationPrivKey.value(), serialDecimal, issuer, subject,
- validityNotBefore, validityNotAfter);
- if (!attestationKeyCertificate) {
+ optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair);
+ if (!privKey) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
- "Error creating certificate for attestationPubKey"));
+ "Error getting private part of credentialKey"));
}
+ credentialPrivKey_ = privKey.value();
- // Concatenate the certificates to form the chain.
- vector<uint8_t> certificateChain;
- certificateChain.insert(certificateChain.end(), credentialPubKeyCertificate.value().begin(),
- credentialPubKeyCertificate.value().end());
- certificateChain.insert(certificateChain.end(), attestationKeyCertificate.value().begin(),
- attestationKeyCertificate.value().end());
-
- optional<vector<vector<uint8_t>>> splitCertChain =
- support::certificateChainSplit(certificateChain);
- if (!splitCertChain) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_FAILED, "Error splitting certificate chain"));
- }
+ // convert from vector<vector<uint8_t>>> to vector<Certificate>*
*outCertificateChain = vector<Certificate>();
- for (const vector<uint8_t>& cert : splitCertChain.value()) {
+ for (const vector<uint8_t>& cert : certificateChain_) {
Certificate c = Certificate();
c.encodedCertificate = byteStringToSigned(cert);
outCertificateChain->push_back(std::move(c));
diff --git a/identity/aidl/default/WritableIdentityCredential.h b/identity/aidl/default/WritableIdentityCredential.h
index b380f89..b182862 100644
--- a/identity/aidl/default/WritableIdentityCredential.h
+++ b/identity/aidl/default/WritableIdentityCredential.h
@@ -64,10 +64,13 @@
string docType_;
bool testCredential_;
- // These are set in initialize().
+ // This is set in initialize().
vector<uint8_t> storageKey_;
+
+ // These are set in getAttestationCertificate().
vector<uint8_t> credentialPrivKey_;
vector<uint8_t> credentialPubKey_;
+ vector<vector<uint8_t>> certificateChain_;
// These fields are initialized during startPersonalization()
size_t numAccessControlProfileRemaining_;
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 21ff440..cecc814 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -7,10 +7,11 @@
srcs: ["VtsHalIdentityTargetTest.cpp"],
shared_libs: [
"libbinder",
- "libcppbor",
- "android.hardware.identity-support-lib",
+ "libcrypto",
],
static_libs: [
+ "libcppbor",
+ "android.hardware.identity-support-lib",
"android.hardware.identity-cpp",
"android.hardware.keymaster-cpp",
],
diff --git a/identity/aidl/vts/VtsHalIdentityTargetTest.cpp b/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
index 5abe5a2..ea37fdc 100644
--- a/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
@@ -352,10 +352,15 @@
readerCertificate.value());
ASSERT_TRUE(readerSignature);
+ // Generate the key that will be used to sign AuthenticatedData.
+ vector<uint8_t> signingKeyBlob;
+ Certificate signingKeyCertificate;
+ ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+
ASSERT_TRUE(credential
->startRetrieval(returnedSecureProfiles, authToken, itemsRequestBytes,
- sessionTranscriptBytes, readerSignature.value(),
- testEntriesEntryCounts)
+ signingKeyBlob, sessionTranscriptBytes,
+ readerSignature.value(), testEntriesEntryCounts)
.isOk());
for (const auto& entry : testEntries) {
@@ -377,14 +382,9 @@
EXPECT_EQ(content, entry.valueCbor);
}
- // Generate the key that will be used to sign AuthenticatedData.
- vector<uint8_t> signingKeyBlob;
- Certificate signingKeyCertificate;
- ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
-
vector<uint8_t> mac;
vector<uint8_t> deviceNameSpacesBytes;
- ASSERT_TRUE(credential->finishRetrieval(signingKeyBlob, &mac, &deviceNameSpacesBytes).isOk());
+ ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
ASSERT_EQ(
"{\n"
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 7b4546b..2b6c695 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -23,10 +23,14 @@
"include",
],
shared_libs: [
+ "android.hardware.keymaster@4.0",
"libcrypto",
"libbase",
"libhidlbase",
"libhardware",
+ "libkeymaster_portable",
+ "libsoft_attestation_cert",
+ "libpuresoftkeymasterdevice",
],
static_libs: [
"libcppbor",
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index 4533ad9..507e914 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -21,6 +21,7 @@
#include <optional>
#include <string>
#include <tuple>
+#include <utility>
#include <vector>
namespace android {
@@ -106,6 +107,17 @@
// ---------------------------------------------------------------------------
// EC crypto functionality / abstraction (only supports P-256).
// ---------------------------------------------------------------------------
+// Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
+// PKCS#8 encoded key-pair. Also generates an attestation
+// certificate using the |challenge| and |applicationId|, and returns the generated
+// certificate in X.509 certificate chain format.
+//
+// The attestation time fields used will be the current time, and expires in one year.
+//
+// The first parameter of the return value is the keyPair generated, second return in
+// the pair is the attestation certificate generated.
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId);
// Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
// PKCS#8 encoded key-pair.
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index e2828bf..bf6a5c3 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -47,6 +47,13 @@
#include <cppbor.h>
#include <cppbor_parse.h>
+#include <android/hardware/keymaster/4.0/types.h>
+#include <keymaster/authorization_set.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/contexts/soft_attestation_cert.h>
+#include <keymaster/keymaster_tags.h>
+#include <keymaster/km_openssl/attestation_utils.h>
+
namespace android {
namespace hardware {
namespace identity {
@@ -816,6 +823,138 @@
return hmac;
}
+// Generates the attestation certificate with the parameters passed in. Note
+// that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
+// milli seconds since epoch. We are setting them to milliseconds due to
+// requirement in AuthorizationSet KM_DATE fields. The certificate created is
+// actually in seconds.
+optional<vector<vector<uint8_t>>> createAttestation(const EVP_PKEY* key,
+ const vector<uint8_t>& applicationId,
+ const vector<uint8_t>& challenge,
+ uint64_t activeTimeMilliSeconds,
+ uint64_t expireTimeMilliSeconds) {
+ ::keymaster::AuthorizationSet auth_set(
+ ::keymaster::AuthorizationSetBuilder()
+ .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
+ challenge.size())
+ .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
+ // Even though identity attestation hal said the application
+ // id should be in software enforced authentication set,
+ // keymaster portable lib expect the input in this
+ // parameter because the software enforced in input to keymaster
+ // refers to the key software enforced properties. And this
+ // parameter refers to properties of the attestation which
+ // includes app id.
+ .Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
+ applicationId.data(), applicationId.size())
+ .Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
+
+ // Unique id and device id is not applicable for identity credential attestation,
+ // so we don't need to set those or application id.
+ ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
+ ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
+
+ ::keymaster::AuthorizationSet hwEnforced(
+ ::keymaster::AuthorizationSetBuilder()
+ .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
+ .Authorization(::keymaster::TAG_KEY_SIZE, 256)
+ .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
+ .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
+ .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
+ .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
+ .Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
+
+ const keymaster_cert_chain_t* attestation_chain =
+ ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
+
+ if (attestation_chain == nullptr) {
+ LOG(ERROR) << "Error getting attestation chain";
+ return {};
+ }
+
+ const keymaster_key_blob_t* attestation_signing_key =
+ ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
+ if (attestation_signing_key == nullptr) {
+ LOG(ERROR) << "Error getting attestation key";
+ return {};
+ }
+
+ keymaster_error_t error;
+ ::keymaster::CertChainPtr cert_chain_out;
+ ::keymaster::PureSoftKeymasterContext context;
+
+ // set identity version to 10 per hal requirements specified in IWriteableCredential.hal
+ // For now, the identity version in the attestation is set in the keymaster
+ // version field in the portable keymaster lib, which is a bit misleading.
+ uint identity_version = 10;
+ error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
+ identity_version, *attestation_chain,
+ *attestation_signing_key, &cert_chain_out);
+
+ if (KM_ERROR_OK != error || !cert_chain_out) {
+ LOG(ERROR) << "Error generate attestation from EVP key" << error;
+ return {};
+ }
+
+ // translate certificate format from keymaster_cert_chain_t to vector<uint8_t>.
+ vector<vector<uint8_t>> attestationCertificate;
+ for (int i = 0; i < cert_chain_out->entry_count; i++) {
+ attestationCertificate.insert(
+ attestationCertificate.end(),
+ vector<uint8_t>(
+ cert_chain_out->entries[i].data,
+ cert_chain_out->entries[i].data + cert_chain_out->entries[i].data_length));
+ }
+
+ return attestationCertificate;
+}
+
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
+ auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
+ auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
+ auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+
+ if (ec_key.get() == nullptr || pkey.get() == nullptr) {
+ LOG(ERROR) << "Memory allocation failed";
+ return {};
+ }
+
+ if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+ EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+ LOG(ERROR) << "Error generating key";
+ return {};
+ }
+
+ if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
+ LOG(ERROR) << "Error getting private key";
+ return {};
+ }
+
+ uint64_t now = time(nullptr);
+ uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
+ uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
+
+ optional<vector<vector<uint8_t>>> attestationCert =
+ createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
+ if (!attestationCert) {
+ LOG(ERROR) << "Error create attestation from key and challenge";
+ return {};
+ }
+
+ int size = i2d_PrivateKey(pkey.get(), nullptr);
+ if (size == 0) {
+ LOG(ERROR) << "Error generating public key encoding";
+ return {};
+ }
+
+ vector<uint8_t> keyPair(size);
+ unsigned char* p = keyPair.data();
+ i2d_PrivateKey(pkey.get(), &p);
+
+ return make_pair(keyPair, attestationCert.value());
+}
+
optional<vector<uint8_t>> createEcKeyPair() {
auto ec_key = EC_KEY_Ptr(EC_KEY_new());
auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
index 6c186f6..40eb142 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -101,6 +101,7 @@
DECLARE_KM_4_1_TYPED_TAG(EARLY_BOOT_ONLY);
DECLARE_KM_4_1_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION);
DECLARE_KM_4_1_TYPED_TAG(STORAGE_KEY);
+DECLARE_KM_4_1_TYPED_TAG(IDENTITY_CREDENTIAL_KEY);
} // namespace android::hardware::keymaster::V4_1
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index cc15263..79d8594 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -24,6 +24,8 @@
using implementation::PreparedModelCallback;
+using PrepareModelMutation = std::function<void(Model*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -54,12 +56,13 @@
}
// Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
- const std::function<void(Model*)>& mutation) {
- mutation(&model);
+// mutation to invalidate the model, then pass these to supportedOperations and
+// prepareModel.
+static void validate(const sp<IDevice>& device, const std::string& message,
+ const Model& originalModel, const PrepareModelMutation& mutate) {
+ Model model = originalModel;
+ mutate(&model);
+
validateGetSupportedOperations(device, message, model);
validatePrepareModel(device, message, model);
}
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
index 05eefd1..0baa85b 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -24,15 +24,17 @@
using implementation::ExecutionCallback;
+using ExecutionMutation = std::function<void(Request*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
// Primary validation function. This function will take a valid request, apply a
// mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
- Request request, const std::function<void(Request*)>& mutation) {
- mutation(&request);
+ const Request& originalRequest, const ExecutionMutation& mutate) {
+ Request request = originalRequest;
+ mutate(&request);
SCOPED_TRACE(message + " [execute]");
sp<ExecutionCallback> executionCallback = new ExecutionCallback();
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index 0629a1e..3b6f0f8 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -30,6 +30,8 @@
using V1_0::OperandType;
using V1_0::implementation::PreparedModelCallback;
+using PrepareModelMutation = std::function<void(Model*, ExecutionPreference*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -67,16 +69,19 @@
}
// Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
- const std::function<void(Model*)>& mutation,
- ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
- mutation(&model);
+// mutation to invalidate either the model or the execution preference, then
+// pass these to supportedOperations and/or prepareModel if that method is
+// called with an invalid argument.
+static void validate(const sp<IDevice>& device, const std::string& message,
+ const Model& originalModel, const PrepareModelMutation& mutate) {
+ Model model = originalModel;
+ ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER;
+ mutate(&model, &preference);
+
if (validExecutionPreference(preference)) {
validateGetSupportedOperations(device, message, model);
}
+
validatePrepareModel(device, message, model, preference);
}
@@ -115,9 +120,11 @@
const std::string message = "mutateOperandTypeTest: operand " +
std::to_string(operand) + " set to value " +
std::to_string(invalidOperandType);
- validate(device, message, model, [operand, invalidOperandType](Model* model) {
- model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
- });
+ validate(device, message, model,
+ [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+ model->operands[operand].type =
+ static_cast<OperandType>(invalidOperandType);
+ });
}
}
}
@@ -144,9 +151,10 @@
const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
" has rank of " + std::to_string(invalidRank);
- validate(device, message, model, [operand, invalidRank](Model* model) {
- model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
- });
+ validate(device, message, model,
+ [operand, invalidRank](Model* model, ExecutionPreference*) {
+ model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+ });
}
}
@@ -173,9 +181,10 @@
const float invalidScale = getInvalidScale(model.operands[operand].type);
const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
" has scale of " + std::to_string(invalidScale);
- validate(device, message, model, [operand, invalidScale](Model* model) {
- model->operands[operand].scale = invalidScale;
- });
+ validate(device, message, model,
+ [operand, invalidScale](Model* model, ExecutionPreference*) {
+ model->operands[operand].scale = invalidScale;
+ });
}
}
@@ -204,9 +213,10 @@
const std::string message = "mutateOperandZeroPointTest: operand " +
std::to_string(operand) + " has zero point of " +
std::to_string(invalidZeroPoint);
- validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
- model->operands[operand].zeroPoint = invalidZeroPoint;
- });
+ validate(device, message, model,
+ [operand, invalidZeroPoint](Model* model, ExecutionPreference*) {
+ model->operands[operand].zeroPoint = invalidZeroPoint;
+ });
}
}
}
@@ -282,9 +292,10 @@
const std::string message = "mutateOperationOperandTypeTest: operand " +
std::to_string(operand) + " set to type " +
toString(invalidOperandType);
- validate(device, message, model, [operand, invalidOperandType](Model* model) {
- mutateOperand(&model->operands[operand], invalidOperandType);
- });
+ validate(device, message, model,
+ [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+ mutateOperand(&model->operands[operand], invalidOperandType);
+ });
}
}
}
@@ -304,10 +315,11 @@
const std::string message = "mutateOperationTypeTest: operation " +
std::to_string(operation) + " set to value " +
std::to_string(invalidOperationType);
- validate(device, message, model, [operation, invalidOperationType](Model* model) {
- model->operations[operation].type =
- static_cast<OperationType>(invalidOperationType);
- });
+ validate(device, message, model,
+ [operation, invalidOperationType](Model* model, ExecutionPreference*) {
+ model->operations[operation].type =
+ static_cast<OperationType>(invalidOperationType);
+ });
}
}
}
@@ -321,9 +333,10 @@
const std::string message = "mutateOperationInputOperandIndexTest: operation " +
std::to_string(operation) + " input " +
std::to_string(input);
- validate(device, message, model, [operation, input, invalidOperand](Model* model) {
- model->operations[operation].inputs[input] = invalidOperand;
- });
+ validate(device, message, model,
+ [operation, input, invalidOperand](Model* model, ExecutionPreference*) {
+ model->operations[operation].inputs[input] = invalidOperand;
+ });
}
}
}
@@ -337,9 +350,10 @@
const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
std::to_string(operation) + " output " +
std::to_string(output);
- validate(device, message, model, [operation, output, invalidOperand](Model* model) {
- model->operations[operation].outputs[output] = invalidOperand;
- });
+ validate(device, message, model,
+ [operation, output, invalidOperand](Model* model, ExecutionPreference*) {
+ model->operations[operation].outputs[output] = invalidOperand;
+ });
}
}
}
@@ -372,7 +386,7 @@
for (size_t operand = 0; operand < model.operands.size(); ++operand) {
const std::string message = "removeOperandTest: operand " + std::to_string(operand);
validate(device, message, model,
- [operand](Model* model) { removeOperand(model, operand); });
+ [operand](Model* model, ExecutionPreference*) { removeOperand(model, operand); });
}
}
@@ -388,8 +402,9 @@
static void removeOperationTest(const sp<IDevice>& device, const Model& model) {
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
const std::string message = "removeOperationTest: operation " + std::to_string(operation);
- validate(device, message, model,
- [operation](Model* model) { removeOperation(model, operation); });
+ validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
+ removeOperation(model, operation);
+ });
}
}
@@ -409,11 +424,12 @@
const std::string message = "removeOperationInputTest: operation " +
std::to_string(operation) + ", input " +
std::to_string(input);
- validate(device, message, model, [operation, input](Model* model) {
- uint32_t operand = model->operations[operation].inputs[input];
- model->operands[operand].numberOfConsumers--;
- hidl_vec_removeAt(&model->operations[operation].inputs, input);
- });
+ validate(device, message, model,
+ [operation, input](Model* model, ExecutionPreference*) {
+ uint32_t operand = model->operations[operation].inputs[input];
+ model->operands[operand].numberOfConsumers--;
+ hidl_vec_removeAt(&model->operations[operation].inputs, input);
+ });
}
}
}
@@ -426,9 +442,10 @@
const std::string message = "removeOperationOutputTest: operation " +
std::to_string(operation) + ", output " +
std::to_string(output);
- validate(device, message, model, [operation, output](Model* model) {
- hidl_vec_removeAt(&model->operations[operation].outputs, output);
- });
+ validate(device, message, model,
+ [operation, output](Model* model, ExecutionPreference*) {
+ hidl_vec_removeAt(&model->operations[operation].outputs, output);
+ });
}
}
}
@@ -444,7 +461,7 @@
static void addOperationInputTest(const sp<IDevice>& device, const Model& model) {
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
- validate(device, message, model, [operation](Model* model) {
+ validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
hidl_vec_push_back(&model->operations[operation].inputs, index);
hidl_vec_push_back(&model->inputIndexes, index);
@@ -458,7 +475,7 @@
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
const std::string message =
"addOperationOutputTest: operation " + std::to_string(operation);
- validate(device, message, model, [operation](Model* model) {
+ validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
hidl_vec_push_back(&model->operations[operation].outputs, index);
hidl_vec_push_back(&model->outputIndexes, index);
@@ -474,12 +491,13 @@
};
static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
- for (int32_t preference : invalidExecutionPreferences) {
+ for (int32_t invalidPreference : invalidExecutionPreferences) {
const std::string message =
- "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
- validate(
- device, message, model, [](Model*) {},
- static_cast<ExecutionPreference>(preference));
+ "mutateExecutionPreferenceTest: preference " + std::to_string(invalidPreference);
+ validate(device, message, model,
+ [invalidPreference](Model*, ExecutionPreference* preference) {
+ *preference = static_cast<ExecutionPreference>(invalidPreference);
+ });
}
}
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
index 9684eb2..2914335 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -28,15 +28,17 @@
using V1_0::Request;
using V1_0::implementation::ExecutionCallback;
+using ExecutionMutation = std::function<void(Request*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
// Primary validation function. This function will take a valid request, apply a
// mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
- Request request, const std::function<void(Request*)>& mutation) {
- mutation(&request);
+ const Request& originalRequest, const ExecutionMutation& mutate) {
+ Request request = originalRequest;
+ mutate(&request);
SCOPED_TRACE(message + " [execute]");
sp<ExecutionCallback> executionCallback = new ExecutionCallback();
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 31a1a81..7c1faee 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -28,7 +28,7 @@
],
header_libs: [
"libbase_headers",
- ]
+ ],
}
cc_test {
@@ -39,9 +39,9 @@
"CompilationCachingTests.cpp",
"GeneratedTestHarness.cpp",
"TestAssertions.cpp",
+ "ValidateBurst.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
- "ValidateBurst.cpp",
"VtsHalNeuralnetworks.cpp",
],
local_include_dirs: ["include"],
@@ -50,18 +50,17 @@
"libnativewindow",
],
static_libs: [
+ "VtsHalNeuralNetworksV1_0_utils",
+ "VtsHalNeuralNetworksV1_2Callbacks",
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"android.hardware.neuralnetworks@1.2",
- "android.hardware.neuralnetworks@1.3",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libgmock",
"libhidlmemory",
"libneuralnetworks_generated_test_harness",
"libneuralnetworks_utils",
- "VtsHalNeuralNetworksV1_0_utils",
- "VtsHalNeuralNetworksV1_2Callbacks",
],
whole_static_libs: [
"neuralnetworks_generated_V1_0_example",
@@ -71,5 +70,8 @@
header_libs: [
"libneuralnetworks_headers",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: [
+ "general-tests",
+ "vts-core",
+ ],
}
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 10dec79..449b8f3 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -32,7 +32,6 @@
#include "GeneratedTestHarness.h"
#include "MemoryUtils.h"
#include "TestHarness.h"
-#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
// Forward declaration of the mobilenet generated test models in
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
index 4c8fede..3ab0135 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -43,7 +43,6 @@
#include "ExecutionBurstController.h"
#include "MemoryUtils.h"
#include "TestHarness.h"
-#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
namespace android::hardware::neuralnetworks::V1_2::vts::functional {
@@ -273,7 +272,7 @@
int n;
std::tie(n, outputShapes, timing, std::ignore) =
controller->compute(request, testConfig.measureTiming, keys);
- executionStatus = nn::convertToV1_0(nn::convertResultCodeToErrorStatus(n));
+ executionStatus = nn::legacyConvertResultCodeToErrorStatus(n);
break;
}
diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
index ec9629b..4476266 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
@@ -23,7 +23,6 @@
#include "ExecutionBurstServer.h"
#include "GeneratedTestHarness.h"
#include "TestHarness.h"
-#include "Utils.h"
#include <android-base/logging.h>
#include <chrono>
@@ -38,6 +37,8 @@
using V1_0::Request;
using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback;
+using BurstExecutionMutation = std::function<void(std::vector<FmqRequestDatum>*)>;
+
// This constant value represents the length of an FMQ that is large enough to
// return a result from a burst execution for all of the generated test cases.
constexpr size_t kExecutionBurstChannelLength = 1024;
@@ -116,13 +117,13 @@
// Primary validation function. This function will take a valid serialized
// request, apply a mutation to it to invalidate the serialized request, then
-// pass it to interface calls that use the serialized request. Note that the
-// serialized request here is passed by value, and any mutation to the
-// serialized request does not leave this function.
+// pass it to interface calls that use the serialized request.
static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiver,
- const std::string& message, std::vector<FmqRequestDatum> serialized,
- const std::function<void(std::vector<FmqRequestDatum>*)>& mutation) {
- mutation(&serialized);
+ const std::string& message,
+ const std::vector<FmqRequestDatum>& originalSerialized,
+ const BurstExecutionMutation& mutate) {
+ std::vector<FmqRequestDatum> serialized = originalSerialized;
+ mutate(&serialized);
// skip if packet is too large to send
if (serialized.size() > kExecutionBurstChannelLength) {
@@ -296,8 +297,7 @@
// collect serialized result by running regular burst
const auto [nRegular, outputShapesRegular, timingRegular, fallbackRegular] =
controllerRegular->compute(request, MeasureTiming::NO, keys);
- const ErrorStatus statusRegular =
- nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nRegular));
+ const ErrorStatus statusRegular = nn::legacyConvertResultCodeToErrorStatus(nRegular);
EXPECT_FALSE(fallbackRegular);
// skip test if regular burst output isn't useful for testing a failure
@@ -313,7 +313,7 @@
// large enough to return the serialized result
const auto [nSmall, outputShapesSmall, timingSmall, fallbackSmall] =
controllerSmall->compute(request, MeasureTiming::NO, keys);
- const ErrorStatus statusSmall = nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nSmall));
+ const ErrorStatus statusSmall = nn::legacyConvertResultCodeToErrorStatus(nSmall);
EXPECT_NE(ErrorStatus::NONE, statusSmall);
EXPECT_EQ(0u, outputShapesSmall.size());
EXPECT_TRUE(badTiming(timingSmall));
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 30530be..7451f09 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -29,6 +29,8 @@
using V1_1::ExecutionPreference;
using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+using PrepareModelMutation = std::function<void(Model*, ExecutionPreference*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -67,16 +69,19 @@
}
// Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
- const std::function<void(Model*)>& mutation,
- ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
- mutation(&model);
+// mutation to invalidate either the model or the execution preference, then
+// pass these to supportedOperations and/or prepareModel if that method is
+// called with an invalid argument.
+static void validate(const sp<IDevice>& device, const std::string& message,
+ const Model& originalModel, const PrepareModelMutation& mutate) {
+ Model model = originalModel;
+ ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER;
+ mutate(&model, &preference);
+
if (validExecutionPreference(preference)) {
validateGetSupportedOperations(device, message, model);
}
+
validatePrepareModel(device, message, model, preference);
}
@@ -115,9 +120,11 @@
const std::string message = "mutateOperandTypeTest: operand " +
std::to_string(operand) + " set to value " +
std::to_string(invalidOperandType);
- validate(device, message, model, [operand, invalidOperandType](Model* model) {
- model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
- });
+ validate(device, message, model,
+ [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+ model->operands[operand].type =
+ static_cast<OperandType>(invalidOperandType);
+ });
}
}
}
@@ -155,9 +162,10 @@
}
const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
" has rank of " + std::to_string(invalidRank);
- validate(device, message, model, [operand, invalidRank](Model* model) {
- model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
- });
+ validate(device, message, model,
+ [operand, invalidRank](Model* model, ExecutionPreference*) {
+ model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+ });
}
}
@@ -192,9 +200,10 @@
const float invalidScale = getInvalidScale(model.operands[operand].type);
const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
" has scale of " + std::to_string(invalidScale);
- validate(device, message, model, [operand, invalidScale](Model* model) {
- model->operands[operand].scale = invalidScale;
- });
+ validate(device, message, model,
+ [operand, invalidScale](Model* model, ExecutionPreference*) {
+ model->operands[operand].scale = invalidScale;
+ });
}
}
@@ -234,9 +243,10 @@
const std::string message = "mutateOperandZeroPointTest: operand " +
std::to_string(operand) + " has zero point of " +
std::to_string(invalidZeroPoint);
- validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
- model->operands[operand].zeroPoint = invalidZeroPoint;
- });
+ validate(device, message, model,
+ [operand, invalidZeroPoint](Model* model, ExecutionPreference*) {
+ model->operands[operand].zeroPoint = invalidZeroPoint;
+ });
}
}
}
@@ -386,9 +396,10 @@
const std::string message = "mutateOperationOperandTypeTest: operand " +
std::to_string(operand) + " set to type " +
toString(invalidOperandType);
- validate(device, message, model, [operand, invalidOperandType](Model* model) {
- mutateOperand(&model->operands[operand], invalidOperandType);
- });
+ validate(device, message, model,
+ [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+ mutateOperand(&model->operands[operand], invalidOperandType);
+ });
}
}
}
@@ -407,10 +418,11 @@
const std::string message = "mutateOperationTypeTest: operation " +
std::to_string(operation) + " set to value " +
std::to_string(invalidOperationType);
- validate(device, message, model, [operation, invalidOperationType](Model* model) {
- model->operations[operation].type =
- static_cast<OperationType>(invalidOperationType);
- });
+ validate(device, message, model,
+ [operation, invalidOperationType](Model* model, ExecutionPreference*) {
+ model->operations[operation].type =
+ static_cast<OperationType>(invalidOperationType);
+ });
}
}
}
@@ -424,9 +436,10 @@
const std::string message = "mutateOperationInputOperandIndexTest: operation " +
std::to_string(operation) + " input " +
std::to_string(input);
- validate(device, message, model, [operation, input, invalidOperand](Model* model) {
- model->operations[operation].inputs[input] = invalidOperand;
- });
+ validate(device, message, model,
+ [operation, input, invalidOperand](Model* model, ExecutionPreference*) {
+ model->operations[operation].inputs[input] = invalidOperand;
+ });
}
}
}
@@ -440,9 +453,10 @@
const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
std::to_string(operation) + " output " +
std::to_string(output);
- validate(device, message, model, [operation, output, invalidOperand](Model* model) {
- model->operations[operation].outputs[output] = invalidOperand;
- });
+ validate(device, message, model,
+ [operation, output, invalidOperand](Model* model, ExecutionPreference*) {
+ model->operations[operation].outputs[output] = invalidOperand;
+ });
}
}
}
@@ -503,7 +517,7 @@
}
const std::string message = "removeOperandTest: operand " + std::to_string(operand);
validate(device, message, model,
- [operand](Model* model) { removeOperand(model, operand); });
+ [operand](Model* model, ExecutionPreference*) { removeOperand(model, operand); });
}
}
@@ -519,8 +533,9 @@
static void removeOperationTest(const sp<IDevice>& device, const Model& model) {
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
const std::string message = "removeOperationTest: operation " + std::to_string(operation);
- validate(device, message, model,
- [operation](Model* model) { removeOperation(model, operation); });
+ validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
+ removeOperation(model, operation);
+ });
}
}
@@ -601,11 +616,12 @@
const std::string message = "removeOperationInputTest: operation " +
std::to_string(operation) + ", input " +
std::to_string(input);
- validate(device, message, model, [operation, input](Model* model) {
- uint32_t operand = model->operations[operation].inputs[input];
- model->operands[operand].numberOfConsumers--;
- hidl_vec_removeAt(&model->operations[operation].inputs, input);
- });
+ validate(device, message, model,
+ [operation, input](Model* model, ExecutionPreference*) {
+ uint32_t operand = model->operations[operation].inputs[input];
+ model->operands[operand].numberOfConsumers--;
+ hidl_vec_removeAt(&model->operations[operation].inputs, input);
+ });
}
}
}
@@ -618,9 +634,10 @@
const std::string message = "removeOperationOutputTest: operation " +
std::to_string(operation) + ", output " +
std::to_string(output);
- validate(device, message, model, [operation, output](Model* model) {
- hidl_vec_removeAt(&model->operations[operation].outputs, output);
- });
+ validate(device, message, model,
+ [operation, output](Model* model, ExecutionPreference*) {
+ hidl_vec_removeAt(&model->operations[operation].outputs, output);
+ });
}
}
}
@@ -651,7 +668,7 @@
continue;
}
const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
- validate(device, message, model, [operation](Model* model) {
+ validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
hidl_vec_push_back(&model->operations[operation].inputs, index);
hidl_vec_push_back(&model->inputIndexes, index);
@@ -665,7 +682,7 @@
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
const std::string message =
"addOperationOutputTest: operation " + std::to_string(operation);
- validate(device, message, model, [operation](Model* model) {
+ validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
hidl_vec_push_back(&model->operations[operation].outputs, index);
hidl_vec_push_back(&model->outputIndexes, index);
@@ -681,12 +698,13 @@
};
static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
- for (int32_t preference : invalidExecutionPreferences) {
+ for (int32_t invalidPreference : invalidExecutionPreferences) {
const std::string message =
- "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
- validate(
- device, message, model, [](Model*) {},
- static_cast<ExecutionPreference>(preference));
+ "mutateExecutionPreferenceTest: preference " + std::to_string(invalidPreference);
+ validate(device, message, model,
+ [invalidPreference](Model*, ExecutionPreference* preference) {
+ *preference = static_cast<ExecutionPreference>(invalidPreference);
+ });
}
}
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index 7b5ff9b..934d893 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -22,7 +22,6 @@
#include "ExecutionBurstController.h"
#include "GeneratedTestHarness.h"
#include "TestHarness.h"
-#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
namespace android::hardware::neuralnetworks::V1_2::vts::functional {
@@ -31,6 +30,8 @@
using V1_0::ErrorStatus;
using V1_0::Request;
+using ExecutionMutation = std::function<void(Request*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
static bool badTiming(Timing timing) {
@@ -39,11 +40,11 @@
// Primary validation function. This function will take a valid request, apply a
// mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
- Request request, const std::function<void(Request*)>& mutation) {
- mutation(&request);
+ const Request& originalRequest, const ExecutionMutation& mutate) {
+ Request request = originalRequest;
+ mutate(&request);
// We'd like to test both with timing requested and without timing
// requested. Rather than running each test both ways, we'll decide whether
@@ -107,7 +108,7 @@
// execute and verify
const auto [n, outputShapes, timing, fallback] = burst->compute(request, measure, keys);
- const ErrorStatus status = nn::convertToV1_0(nn::convertResultCodeToErrorStatus(n));
+ const ErrorStatus status = nn::legacyConvertResultCodeToErrorStatus(n);
EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
EXPECT_EQ(outputShapes.size(), 0);
EXPECT_TRUE(badTiming(timing));
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index daaf22e..25ec915 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -5168,6 +5168,8 @@
* * {@link OperandType::TENSOR_FLOAT16}
* * {@link OperandType::TENSOR_FLOAT32}
*
+ * Supported tensor rank: from 1.
+ *
* Inputs:
* * 0: A tensor, specifying the input. May be zero-sized.
* * 1: A scalar, specifying the alpha parameter.
@@ -5197,6 +5199,8 @@
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
* * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
*
+ * Supported tensor rank: from 1.
+ *
* Inputs:
* * 0: A tensor, specifying the input. May be zero-sized.
*
@@ -5215,6 +5219,8 @@
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_INT32}
*
+ * Supported tensor rank: from 1.
+ *
* Inputs:
* * 0: A 1-D tensor, specifying the desired output tensor shape.
* * 1: A scalar, specifying the value to fill the output tensors with.
@@ -5248,6 +5254,8 @@
* * {@link OperandType::TENSOR_QUANT8_SYMM}
* * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
*
+ * Supported tensor rank: from 1.
+ *
* Inputs:
* * 0: The input tensor.
*
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 8c9393b..5689a39 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -493,6 +493,13 @@
return outputBuffers;
}
+static bool hasZeroSizedOutput(const TestModel& testModel) {
+ return std::any_of(testModel.main.outputIndexes.begin(), testModel.main.outputIndexes.end(),
+ [&testModel](uint32_t index) {
+ return testModel.main.operands[index].data.size() == 0;
+ });
+}
+
static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
const Request& request, MeasureTiming measure,
const OptionalTimeoutDuration& loopTimeoutDuration,
@@ -626,21 +633,28 @@
ErrorStatus result;
hidl_handle syncFenceHandle;
sp<IFencedExecutionCallback> fencedCallback;
- Return<void> ret = preparedModel->executeFenced(
- request, {}, testConfig.measureTiming, {}, loopTimeoutDuration, {},
- [&result, &syncFenceHandle, &fencedCallback](
- ErrorStatus error, const hidl_handle& handle,
- const sp<IFencedExecutionCallback>& callback) {
- result = error;
- syncFenceHandle = handle;
- fencedCallback = callback;
- });
+ auto callbackFunc = [&result, &syncFenceHandle, &fencedCallback](
+ ErrorStatus error, const hidl_handle& handle,
+ const sp<IFencedExecutionCallback>& callback) {
+ result = error;
+ syncFenceHandle = handle;
+ fencedCallback = callback;
+ };
+ Return<void> ret =
+ preparedModel->executeFenced(request, {}, testConfig.measureTiming, {},
+ loopTimeoutDuration, {}, callbackFunc);
ASSERT_TRUE(ret.isOk());
if (result != ErrorStatus::NONE) {
ASSERT_EQ(syncFenceHandle.getNativeHandle(), nullptr);
ASSERT_EQ(fencedCallback, nullptr);
- executionStatus = ErrorStatus::GENERAL_FAILURE;
+ executionStatus = result;
} else if (syncFenceHandle.getNativeHandle()) {
+ // If a sync fence is returned, try start another run waiting for the sync fence.
+ ret = preparedModel->executeFenced(request, {syncFenceHandle},
+ testConfig.measureTiming, {},
+ loopTimeoutDuration, {}, callbackFunc);
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(result, ErrorStatus::NONE);
waitForSyncFence(syncFenceHandle.getNativeHandle()->data[0]);
}
if (result == ErrorStatus::NONE) {
@@ -656,9 +670,7 @@
}
}
- // The driver is allowed to reject executeFenced, and if they do, we should skip.
- if ((testConfig.outputType != OutputType::FULLY_SPECIFIED ||
- testConfig.executor == Executor::FENCED) &&
+ if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
executionStatus == ErrorStatus::GENERAL_FAILURE) {
if (skipped != nullptr) {
*skipped = true;
@@ -684,6 +696,11 @@
switch (testConfig.outputType) {
case OutputType::FULLY_SPECIFIED:
+ if (testConfig.executor == Executor::FENCED && hasZeroSizedOutput(testModel)) {
+ // Executor::FENCED does not support zero-sized output.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
// If the model output operands are fully specified, outputShapes must be either
// either empty, or have the same number of elements as the number of outputs.
ASSERT_EQ(ErrorStatus::NONE, executionStatus);
@@ -691,12 +708,22 @@
outputShapes.size() == testModel.main.outputIndexes.size());
break;
case OutputType::UNSPECIFIED:
+ if (testConfig.executor == Executor::FENCED) {
+ // For Executor::FENCED, the output shape must be fully specified.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
// If the model output operands are not fully specified, outputShapes must have
// the same number of elements as the number of outputs.
ASSERT_EQ(ErrorStatus::NONE, executionStatus);
ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
break;
case OutputType::INSUFFICIENT:
+ if (testConfig.executor == Executor::FENCED) {
+ // For Executor::FENCED, the output shape must be fully specified.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
ASSERT_FALSE(outputShapes[0].isSufficient);
@@ -739,12 +766,12 @@
case TestKind::DYNAMIC_SHAPE: {
outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
- executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+ executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST, Executor::FENCED};
} break;
case TestKind::MEMORY_DOMAIN: {
outputTypesList = {OutputType::FULLY_SPECIFIED};
measureTimingList = {MeasureTiming::NO};
- executorList = {Executor::ASYNC, Executor::SYNC};
+ executorList = {Executor::ASYNC, Executor::SYNC, Executor::FENCED};
memoryType = MemoryType::DEVICE;
} break;
case TestKind::FENCED_COMPUTE: {
@@ -925,7 +952,8 @@
[](const TestModel& testModel) { return !testModel.expectFailure; });
INSTANTIATE_GENERATED_TEST(QuantizationCouplingTest, [](const TestModel& testModel) {
- return testModel.hasQuant8CoupledOperands() && testModel.main.operations.size() == 1;
+ return !testModel.expectFailure && testModel.hasQuant8CoupledOperands() &&
+ testModel.main.operations.size() == 1;
});
INSTANTIATE_GENERATED_TEST(InfiniteLoopTimeoutTest, [](const TestModel& testModel) {
diff --git a/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp
index 6ff9dfd..c78439c 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp
@@ -23,7 +23,6 @@
#include "ExecutionBurstServer.h"
#include "GeneratedTestHarness.h"
#include "TestHarness.h"
-#include "Utils.h"
#include <android-base/logging.h>
#include <chrono>
@@ -43,6 +42,8 @@
using V1_2::Timing;
using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback;
+using BurstExecutionMutation = std::function<void(std::vector<FmqRequestDatum>*)>;
+
// This constant value represents the length of an FMQ that is large enough to
// return a result from a burst execution for all of the generated test cases.
constexpr size_t kExecutionBurstChannelLength = 1024;
@@ -122,13 +123,13 @@
// Primary validation function. This function will take a valid serialized
// request, apply a mutation to it to invalidate the serialized request, then
-// pass it to interface calls that use the serialized request. Note that the
-// serialized request here is passed by value, and any mutation to the
-// serialized request does not leave this function.
+// pass it to interface calls that use the serialized request.
static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiver,
- const std::string& message, std::vector<FmqRequestDatum> serialized,
- const std::function<void(std::vector<FmqRequestDatum>*)>& mutation) {
- mutation(&serialized);
+ const std::string& message,
+ const std::vector<FmqRequestDatum>& originalSerialized,
+ const BurstExecutionMutation& mutate) {
+ std::vector<FmqRequestDatum> serialized = originalSerialized;
+ mutate(&serialized);
// skip if packet is too large to send
if (serialized.size() > kExecutionBurstChannelLength) {
@@ -302,8 +303,7 @@
// collect serialized result by running regular burst
const auto [nRegular, outputShapesRegular, timingRegular, fallbackRegular] =
controllerRegular->compute(request, MeasureTiming::NO, keys);
- const V1_0::ErrorStatus statusRegular =
- nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nRegular));
+ const V1_0::ErrorStatus statusRegular = nn::legacyConvertResultCodeToErrorStatus(nRegular);
EXPECT_FALSE(fallbackRegular);
// skip test if regular burst output isn't useful for testing a failure
@@ -319,8 +319,7 @@
// large enough to return the serialized result
const auto [nSmall, outputShapesSmall, timingSmall, fallbackSmall] =
controllerSmall->compute(request, MeasureTiming::NO, keys);
- const V1_0::ErrorStatus statusSmall =
- nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nSmall));
+ const V1_0::ErrorStatus statusSmall = nn::legacyConvertResultCodeToErrorStatus(nSmall);
EXPECT_NE(V1_0::ErrorStatus::NONE, statusSmall);
EXPECT_EQ(0u, outputShapesSmall.size());
EXPECT_TRUE(badTiming(timingSmall));
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 7da2da9..4c0100e 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -30,6 +30,8 @@
using HidlToken =
hidl_array<uint8_t, static_cast<uint32_t>(V1_2::Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+using PrepareModelMutation = std::function<void(Model*, ExecutionPreference*, Priority*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -44,13 +46,14 @@
}
static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
- const Model& model, ExecutionPreference preference) {
+ const Model& model, ExecutionPreference preference,
+ Priority priority) {
SCOPED_TRACE(message + " [prepareModel_1_3]");
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_3(
- model, preference, kDefaultPriority, {}, hidl_vec<hidl_handle>(),
- hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
+ Return<ErrorStatus> prepareLaunchStatus =
+ device->prepareModel_1_3(model, preference, priority, {}, hidl_vec<hidl_handle>(),
+ hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
@@ -67,18 +70,26 @@
preference == ExecutionPreference::SUSTAINED_SPEED;
}
+static bool validExecutionPriority(Priority priority) {
+ return priority == Priority::LOW || priority == Priority::MEDIUM || priority == Priority::HIGH;
+}
+
// Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
- const std::function<void(Model*)>& mutation,
- ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
- mutation(&model);
- if (validExecutionPreference(preference)) {
+// mutation to invalidate the model, the execution preference, or the priority,
+// then pass these to supportedOperations and/or prepareModel if that method is
+// called with an invalid argument.
+static void validate(const sp<IDevice>& device, const std::string& message,
+ const Model& originalModel, const PrepareModelMutation& mutate) {
+ Model model = originalModel;
+ ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER;
+ Priority priority = kDefaultPriority;
+ mutate(&model, &preference, &priority);
+
+ if (validExecutionPreference(preference) && validExecutionPriority(priority)) {
validateGetSupportedOperations(device, message, model);
}
- validatePrepareModel(device, message, model, preference);
+
+ validatePrepareModel(device, message, model, preference, priority);
}
static uint32_t addOperand(Model* model) {
@@ -116,9 +127,11 @@
const std::string message = "mutateOperandTypeTest: operand " +
std::to_string(operand) + " set to value " +
std::to_string(invalidOperandType);
- validate(device, message, model, [operand, invalidOperandType](Model* model) {
- model->main.operands[operand].type = static_cast<OperandType>(invalidOperandType);
- });
+ validate(device, message, model,
+ [operand, invalidOperandType](Model* model, ExecutionPreference*, Priority*) {
+ model->main.operands[operand].type =
+ static_cast<OperandType>(invalidOperandType);
+ });
}
}
}
@@ -156,9 +169,11 @@
}
const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
" has rank of " + std::to_string(invalidRank);
- validate(device, message, model, [operand, invalidRank](Model* model) {
- model->main.operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
- });
+ validate(device, message, model,
+ [operand, invalidRank](Model* model, ExecutionPreference*, Priority*) {
+ model->main.operands[operand].dimensions =
+ std::vector<uint32_t>(invalidRank, 0);
+ });
}
}
@@ -194,9 +209,10 @@
const float invalidScale = getInvalidScale(model.main.operands[operand].type);
const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
" has scale of " + std::to_string(invalidScale);
- validate(device, message, model, [operand, invalidScale](Model* model) {
- model->main.operands[operand].scale = invalidScale;
- });
+ validate(device, message, model,
+ [operand, invalidScale](Model* model, ExecutionPreference*, Priority*) {
+ model->main.operands[operand].scale = invalidScale;
+ });
}
}
@@ -237,9 +253,10 @@
const std::string message = "mutateOperandZeroPointTest: operand " +
std::to_string(operand) + " has zero point of " +
std::to_string(invalidZeroPoint);
- validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
- model->main.operands[operand].zeroPoint = invalidZeroPoint;
- });
+ validate(device, message, model,
+ [operand, invalidZeroPoint](Model* model, ExecutionPreference*, Priority*) {
+ model->main.operands[operand].zeroPoint = invalidZeroPoint;
+ });
}
}
}
@@ -425,9 +442,10 @@
const std::string message = "mutateOperationOperandTypeTest: operand " +
std::to_string(operand) + " set to type " +
toString(invalidOperandType);
- validate(device, message, model, [operand, invalidOperandType](Model* model) {
- mutateOperand(&model->main.operands[operand], invalidOperandType);
- });
+ validate(device, message, model,
+ [operand, invalidOperandType](Model* model, ExecutionPreference*, Priority*) {
+ mutateOperand(&model->main.operands[operand], invalidOperandType);
+ });
}
}
}
@@ -446,10 +464,12 @@
const std::string message = "mutateOperationTypeTest: operation " +
std::to_string(operation) + " set to value " +
std::to_string(invalidOperationType);
- validate(device, message, model, [operation, invalidOperationType](Model* model) {
- model->main.operations[operation].type =
- static_cast<OperationType>(invalidOperationType);
- });
+ validate(device, message, model,
+ [operation, invalidOperationType](Model* model, ExecutionPreference*,
+ Priority*) {
+ model->main.operations[operation].type =
+ static_cast<OperationType>(invalidOperationType);
+ });
}
}
}
@@ -463,9 +483,11 @@
const std::string message = "mutateOperationInputOperandIndexTest: operation " +
std::to_string(operation) + " input " +
std::to_string(input);
- validate(device, message, model, [operation, input, invalidOperand](Model* model) {
- model->main.operations[operation].inputs[input] = invalidOperand;
- });
+ validate(device, message, model,
+ [operation, input, invalidOperand](Model* model, ExecutionPreference*,
+ Priority*) {
+ model->main.operations[operation].inputs[input] = invalidOperand;
+ });
}
}
}
@@ -480,9 +502,11 @@
const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
std::to_string(operation) + " output " +
std::to_string(output);
- validate(device, message, model, [operation, output, invalidOperand](Model* model) {
- model->main.operations[operation].outputs[output] = invalidOperand;
- });
+ validate(device, message, model,
+ [operation, output, invalidOperand](Model* model, ExecutionPreference*,
+ Priority*) {
+ model->main.operations[operation].outputs[output] = invalidOperand;
+ });
}
}
}
@@ -548,8 +572,9 @@
continue;
}
const std::string message = "removeOperandTest: operand " + std::to_string(operand);
- validate(device, message, model,
- [operand](Model* model) { removeOperand(model, operand); });
+ validate(device, message, model, [operand](Model* model, ExecutionPreference*, Priority*) {
+ removeOperand(model, operand);
+ });
}
}
@@ -566,7 +591,9 @@
for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
const std::string message = "removeOperationTest: operation " + std::to_string(operation);
validate(device, message, model,
- [operation](Model* model) { removeOperation(model, operation); });
+ [operation](Model* model, ExecutionPreference*, Priority*) {
+ removeOperation(model, operation);
+ });
}
}
@@ -654,11 +681,12 @@
const std::string message = "removeOperationInputTest: operation " +
std::to_string(operation) + ", input " +
std::to_string(input);
- validate(device, message, model, [operation, input](Model* model) {
- uint32_t operand = model->main.operations[operation].inputs[input];
- model->main.operands[operand].numberOfConsumers--;
- hidl_vec_removeAt(&model->main.operations[operation].inputs, input);
- });
+ validate(device, message, model,
+ [operation, input](Model* model, ExecutionPreference*, Priority*) {
+ uint32_t operand = model->main.operations[operation].inputs[input];
+ model->main.operands[operand].numberOfConsumers--;
+ hidl_vec_removeAt(&model->main.operations[operation].inputs, input);
+ });
}
}
}
@@ -672,9 +700,10 @@
const std::string message = "removeOperationOutputTest: operation " +
std::to_string(operation) + ", output " +
std::to_string(output);
- validate(device, message, model, [operation, output](Model* model) {
- hidl_vec_removeAt(&model->main.operations[operation].outputs, output);
- });
+ validate(device, message, model,
+ [operation, output](Model* model, ExecutionPreference*, Priority*) {
+ hidl_vec_removeAt(&model->main.operations[operation].outputs, output);
+ });
}
}
}
@@ -707,11 +736,12 @@
continue;
}
const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
- validate(device, message, model, [operation](Model* model) {
- uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_INPUT);
- hidl_vec_push_back(&model->main.operations[operation].inputs, index);
- hidl_vec_push_back(&model->main.inputIndexes, index);
- });
+ validate(device, message, model,
+ [operation](Model* model, ExecutionPreference*, Priority*) {
+ uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_INPUT);
+ hidl_vec_push_back(&model->main.operations[operation].inputs, index);
+ hidl_vec_push_back(&model->main.inputIndexes, index);
+ });
}
}
@@ -721,11 +751,12 @@
for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
const std::string message =
"addOperationOutputTest: operation " + std::to_string(operation);
- validate(device, message, model, [operation](Model* model) {
- uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_OUTPUT);
- hidl_vec_push_back(&model->main.operations[operation].outputs, index);
- hidl_vec_push_back(&model->main.outputIndexes, index);
- });
+ validate(device, message, model,
+ [operation](Model* model, ExecutionPreference*, Priority*) {
+ uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_OUTPUT);
+ hidl_vec_push_back(&model->main.operations[operation].outputs, index);
+ hidl_vec_push_back(&model->main.outputIndexes, index);
+ });
}
}
@@ -737,12 +768,31 @@
};
static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
- for (int32_t preference : invalidExecutionPreferences) {
+ for (int32_t invalidPreference : invalidExecutionPreferences) {
const std::string message =
- "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
- validate(
- device, message, model, [](Model*) {},
- static_cast<ExecutionPreference>(preference));
+ "mutateExecutionPreferenceTest: preference " + std::to_string(invalidPreference);
+ validate(device, message, model,
+ [invalidPreference](Model*, ExecutionPreference* preference, Priority*) {
+ *preference = static_cast<ExecutionPreference>(invalidPreference);
+ });
+ }
+}
+
+///////////////////////// VALIDATE PRIORITY /////////////////////////
+
+static const int32_t invalidPriorities[] = {
+ static_cast<int32_t>(Priority::LOW) - 1, // lower bound
+ static_cast<int32_t>(Priority::HIGH) + 1, // upper bound
+};
+
+static void mutateExecutionPriorityTest(const sp<IDevice>& device, const Model& model) {
+ for (int32_t invalidPriority : invalidPriorities) {
+ const std::string message =
+ "mutatePriorityTest: priority " + std::to_string(invalidPriority);
+ validate(device, message, model,
+ [invalidPriority](Model*, ExecutionPreference*, Priority* priority) {
+ *priority = static_cast<Priority>(invalidPriority);
+ });
}
}
@@ -764,6 +814,7 @@
addOperationInputTest(device, model);
addOperationOutputTest(device, model);
mutateExecutionPreferenceTest(device, model);
+ mutateExecutionPriorityTest(device, model);
}
} // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
index 5e806e5..1ae8b3f 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
@@ -34,6 +34,8 @@
using V1_2::OutputShape;
using V1_2::Timing;
+using ExecutionMutation = std::function<void(Request*)>;
+
///////////////////////// UTILITY FUNCTIONS /////////////////////////
static bool badTiming(Timing timing) {
@@ -42,11 +44,11 @@
// Primary validation function. This function will take a valid request, apply a
// mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
- Request request, const std::function<void(Request*)>& mutation) {
- mutation(&request);
+ const Request& originalRequest, const ExecutionMutation& mutate) {
+ Request request = originalRequest;
+ mutate(&request);
// We'd like to test both with timing requested and without timing
// requested. Rather than running each test both ways, we'll decide whether
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index d04cb36..9b6cc96 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -578,7 +578,7 @@
TEST_P(RadioHidlTest, nvResetConfig) {
serial = GetRandomSerialNumber();
- radio->nvResetConfig(serial, ResetNvType::ERASE);
+ radio->nvResetConfig(serial, ResetNvType::FACTORY_RESET);
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
diff --git a/radio/1.5/IRadio.hal b/radio/1.5/IRadio.hal
index 87824e2..956f9bd 100644
--- a/radio/1.5/IRadio.hal
+++ b/radio/1.5/IRadio.hal
@@ -325,11 +325,15 @@
oneway sendCdmaSmsExpectMore(int32_t serial, CdmaSmsMessage sms);
/**
- * Requests that deactivates one category of the device personalization.
+ * Request that deactivates one category of device personalization. Device personalization
+ * generally binds the device so it can only be used on one carrier or even one carrier subnet
+ * (See TS 22.022). When the user has gained the rights to unbind the device (at the end of a
+ * contract period or other event), the controlKey will be delivered to either the user for
+ * manual entry or to a carrier app on the device for automatic entry.
*
* @param serial Serial number of request.
* @param persoType SIM personalization type.
- * @param controlKey depersonalization code corresponding to persoType
+ * @param controlKey the unlock code for removing persoType personalization from this device
*
* Response function is IRadioResponse.supplySimDepersonalizationResponse()
*/
diff --git a/radio/1.5/IRadioIndication.hal b/radio/1.5/IRadioIndication.hal
index c40b473..58e988f 100644
--- a/radio/1.5/IRadioIndication.hal
+++ b/radio/1.5/IRadioIndication.hal
@@ -95,4 +95,21 @@
* CellInfo.
*/
oneway networkScanResult_1_5(RadioIndicationType type, NetworkScanResult result);
+
+ /**
+ * Indicates data call contexts have changed.
+ *
+ * This indication is updated from IRadioIndication@1.4 to report the @1.5 version of
+ * SetupDataCallResult.
+ *
+ * @param type Type of radio indication
+ * @param dcList Array of SetupDataCallResult identical to that returned by
+ * IRadio.getDataCallList(). It is the complete list of current data contexts including
+ * new contexts that have been activated. A data call is only removed from this list
+ * when below conditions matched.
+ * 1. The framework sends a IRadio.deactivateDataCall().
+ * 2. The radio is powered off/on.
+ * 3. Unsolicited disconnect from either modem or network side.
+ */
+ oneway dataCallListChanged_1_5(RadioIndicationType type, vec<SetupDataCallResult> dcList);
};
diff --git a/radio/1.5/IRadioResponse.hal b/radio/1.5/IRadioResponse.hal
index e87cad2..1380da3 100644
--- a/radio/1.5/IRadioResponse.hal
+++ b/radio/1.5/IRadioResponse.hal
@@ -20,6 +20,7 @@
import @1.0::SendSmsResult;
import @1.4::IRadioResponse;
import @1.5::BarringInfo;
+import @1.5::CardStatus;
import @1.5::CellIdentity;
import @1.5::CellInfo;
import @1.5::PersoSubstate;
@@ -120,6 +121,20 @@
/**
* @param info Response info struct containing response type, serial no. and error
+ * @param dcResponse List of SetupDataCallResult as defined in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:SIM_ABSENT
+ */
+ oneway getDataCallListResponse_1_5(RadioResponseInfo info, vec<SetupDataCallResult> dcResponse);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
*
* Valid errors returned:
* RadioError:NONE
@@ -303,5 +318,18 @@
* RadioError:REQUEST_NOT_SUPPORTED
*/
oneway supplySimDepersonalizationResponse(RadioResponseInfo info,
- PersoSubstate persoType, int32_t remainingRetries);
+ PersoSubstate persoType, int32_t remainingRetries);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param cardStatus ICC card status as defined by CardStatus in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:NO_RESOURCES
+ * RadioError:REQUEST_NOT_SUPPORTED
+ */
+ oneway getIccCardStatusResponse_1_5(RadioResponseInfo info, CardStatus cardStatus);
};
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index 4d3c2d5..45f3b90 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -17,6 +17,7 @@
package android.hardware.radio@1.5;
import @1.0::ApnAuthType;
+import @1.0::AppStatus;
import @1.0::DataProfileId;
import @1.0::DataProfileInfoType;
import @1.0::GsmSignalStrength;
@@ -43,6 +44,7 @@
import @1.2::WcdmaSignalStrength;
import @1.4::AccessNetwork;
import @1.4::ApnTypes;
+import @1.4::CardStatus;
import @1.4::CellIdentityNr;
import @1.4::DataCallFailCause;
import @1.4::DataConnActiveStatus;
@@ -1034,3 +1036,20 @@
SIM_NS_SP,
SIM_NS_SP_PUK,
};
+
+/** Extended from @1.0::AppStatus to update PersoSubstate to 1.5 version. */
+struct AppStatus {
+ @1.0::AppStatus base;
+
+ /** Applicable only if appState == SUBSCRIPTION_PERSO */
+ PersoSubstate persoSubstate;
+};
+
+
+/** Extended from @1.4::CardStatus to use 1.5 version of AppStatus. */
+struct CardStatus {
+ @1.4::CardStatus base;
+
+ /** size <= RadioConst::CARD_MAX_APPS */
+ vec<AppStatus> applications;
+};
diff --git a/radio/1.5/vts/functional/Android.bp b/radio/1.5/vts/functional/Android.bp
index 85c4f99..cd30f7d 100644
--- a/radio/1.5/vts/functional/Android.bp
+++ b/radio/1.5/vts/functional/Android.bp
@@ -36,5 +36,5 @@
"android.hardware.radio.config@1.1",
],
header_libs: ["radio.util.header@1.0"],
- test_suites: ["general-tests"]
+ test_suites: ["general-tests", "vts-core"]
}
diff --git a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
index 5f11d19..31466c5 100644
--- a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
+++ b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
@@ -16,11 +16,7 @@
#include <radio_hidl_hal_utils_v1_5.h>
-int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- RadioHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_5,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ android::hardware::radio::V1_5::IRadio::descriptor)),
+ android::hardware::PrintInstanceNameToString);
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 435bd23..32c02cb 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -21,7 +21,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() with invalid hysteresisDb
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_invalidHysteresisDb) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_invalidHysteresisDb) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -46,7 +46,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() with empty thresholds
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_EmptyThresholds) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_EmptyThresholds) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -70,7 +70,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for GERAN
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Geran) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Geran) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -95,7 +95,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for UTRAN
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Utran) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Utran) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -120,7 +120,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for EUTRAN
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Eutran_RSRP) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Eutran_RSRP) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -145,7 +145,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for EUTRAN
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Eutran_RSRQ) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Eutran_RSRQ) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -170,7 +170,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for EUTRAN
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Eutran_RSSNR) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Eutran_RSSNR) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -191,7 +191,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for CDMA2000
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Cdma2000) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Cdma2000) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -216,7 +216,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for NGRAN_SSRSRP
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSRSRP) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSRSRP) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -241,7 +241,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for NGRAN_SSRSRQ
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSRSRQ) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSRSRQ) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -266,7 +266,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for EUTRAN
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Disable_RSSNR) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Disable_RSSNR) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -287,7 +287,7 @@
/*
* Test IRadio.setSignalStrengthReportingCriteria_1_5() for NGRAN_SSSINR
*/
-TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSSINR) {
+TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSSINR) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
@@ -312,7 +312,7 @@
/*
* Test IRadio.setLinkCapacityReportingCriteria_1_5() invalid hysteresisDlKbps
*/
-TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisDlKbps) {
+TEST_P(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisDlKbps) {
serial = GetRandomSerialNumber();
Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
@@ -337,7 +337,7 @@
/*
* Test IRadio.setLinkCapacityReportingCriteria_1_5() invalid hysteresisUlKbps
*/
-TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisUlKbps) {
+TEST_P(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisUlKbps) {
serial = GetRandomSerialNumber();
Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
@@ -362,7 +362,7 @@
/*
* Test IRadio.setLinkCapacityReportingCriteria_1_5() empty params
*/
-TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_emptyParams) {
+TEST_P(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_emptyParams) {
serial = GetRandomSerialNumber();
Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
@@ -383,7 +383,7 @@
/*
* Test IRadio.setLinkCapacityReportingCriteria_1_5() for GERAN
*/
-TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_Geran) {
+TEST_P(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_Geran) {
serial = GetRandomSerialNumber();
Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
@@ -406,9 +406,9 @@
* Test IRadio.enableUiccApplications() for the response returned.
* For SIM ABSENT case.
*/
-TEST_F(RadioHidlTest_v1_5, togglingUiccApplicationsSimAbsent) {
+TEST_P(RadioHidlTest_v1_5, togglingUiccApplicationsSimAbsent) {
// This test case only test SIM ABSENT case.
- if (cardStatus.base.base.cardState != CardState::ABSENT) return;
+ if (cardStatus.base.base.base.cardState != CardState::ABSENT) return;
// Disable Uicc applications.
serial = GetRandomSerialNumber();
@@ -433,9 +433,9 @@
* Test IRadio.enableUiccApplications() for the response returned.
* For SIM PRESENT case.
*/
-TEST_F(RadioHidlTest_v1_5, togglingUiccApplicationsSimPresent) {
+TEST_P(RadioHidlTest_v1_5, togglingUiccApplicationsSimPresent) {
// This test case only test SIM ABSENT case.
- if (cardStatus.base.base.cardState != CardState::PRESENT) return;
+ if (cardStatus.base.base.base.cardState != CardState::PRESENT) return;
// Disable Uicc applications.
serial = GetRandomSerialNumber();
@@ -479,7 +479,7 @@
/*
* Test IRadio.areUiccApplicationsEnabled() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, areUiccApplicationsEnabled) {
+TEST_P(RadioHidlTest_v1_5, areUiccApplicationsEnabled) {
// Disable Uicc applications.
serial = GetRandomSerialNumber();
radio_v1_5->areUiccApplicationsEnabled(serial);
@@ -489,9 +489,9 @@
// If SIM is absent, RadioError::SIM_ABSENT should be thrown. Otherwise there shouldn't be any
// error.
- if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_v1_5->rspInfo.error);
- } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
}
}
@@ -499,7 +499,7 @@
/*
* Test IRadio.setSystemSelectionChannels_1_5() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
+TEST_P(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -537,7 +537,7 @@
/*
* Test IRadio.startNetworkScan_1_5() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -563,9 +563,9 @@
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) {
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::SIM_ABSENT}));
- } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ } else if (cardStatus.base.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
@@ -578,7 +578,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with invalid specifier.
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidArgument) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidArgument) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::NetworkScanRequest request = {.type = ScanType::ONE_SHOT,
@@ -592,10 +592,10 @@
ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
toString(radioRsp_v1_5->rspInfo.error).c_str());
- if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
@@ -605,7 +605,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with invalid interval (lower boundary).
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval1) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -631,10 +631,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
@@ -644,7 +644,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with invalid interval (upper boundary).
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval2) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -670,10 +670,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
@@ -683,7 +683,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with invalid max search time (lower boundary).
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime1) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -709,10 +709,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
@@ -722,7 +722,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with invalid max search time (upper boundary).
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime2) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -748,10 +748,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
@@ -761,7 +761,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with invalid periodicity (lower boundary).
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity1) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -787,10 +787,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
@@ -800,7 +800,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with invalid periodicity (upper boundary).
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity2) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -826,10 +826,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
@@ -839,7 +839,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with valid periodicity
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -865,10 +865,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
@@ -878,7 +878,7 @@
/*
* Test IRadio.startNetworkScan_1_5() with valid periodicity and plmns
*/
-TEST_F(RadioHidlTest_v1_5, startNetworkScan_GoodRequest2) {
+TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
@@ -905,10 +905,10 @@
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) {
+ if (cardStatus.base.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) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
@@ -918,7 +918,7 @@
/*
* Test IRadio.setupDataCall_1_5() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, setupDataCall_1_5) {
+TEST_P(RadioHidlTest_v1_5, setupDataCall_1_5) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::AccessNetwork accessNetwork =
@@ -961,11 +961,11 @@
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
- if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
- } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
@@ -975,7 +975,7 @@
/*
* Test IRadio.setInitialAttachApn_1_5() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, setInitialAttachApn_1_5) {
+TEST_P(RadioHidlTest_v1_5, setInitialAttachApn_1_5) {
serial = GetRandomSerialNumber();
// Create a dataProfileInfo
@@ -1006,10 +1006,10 @@
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
- if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
- } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
}
@@ -1018,7 +1018,7 @@
/*
* Test IRadio.setDataProfile_1_5() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, setDataProfile_1_5) {
+TEST_P(RadioHidlTest_v1_5, setDataProfile_1_5) {
serial = GetRandomSerialNumber();
// Create a dataProfileInfo
@@ -1053,10 +1053,10 @@
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
- if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
- } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
}
@@ -1065,7 +1065,7 @@
/*
* Test IRadio.setRadioPower_1_5() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, setRadioPower_1_5_emergencyCall_cancelled) {
+TEST_P(RadioHidlTest_v1_5, setRadioPower_1_5_emergencyCall_cancelled) {
// Set radio power to off.
serial = GetRandomSerialNumber();
radio_v1_5->setRadioPower_1_5(serial, false, false, false);
@@ -1096,7 +1096,7 @@
/*
* Test IRadio.setNetworkSelectionModeManual_1_5() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, setNetworkSelectionModeManual_1_5) {
+TEST_P(RadioHidlTest_v1_5, setNetworkSelectionModeManual_1_5) {
serial = GetRandomSerialNumber();
// can't camp on nonexistent MCCMNC, so we expect this to fail.
@@ -1106,12 +1106,12 @@
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
- if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME,
RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
CHECK_GENERAL_ERROR));
- } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+ } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
@@ -1122,7 +1122,7 @@
/*
* Test IRadio.sendCdmaSmsExpectMore() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, sendCdmaSmsExpectMore) {
+TEST_P(RadioHidlTest_v1_5, sendCdmaSmsExpectMore) {
serial = GetRandomSerialNumber();
// Create a CdmaSmsAddress
@@ -1155,7 +1155,7 @@
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
- if (cardStatus.base.base.cardState == CardState::ABSENT) {
+ if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_5->rspInfo.error,
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
@@ -1166,7 +1166,7 @@
/*
* Test IRadio.getBarringInfo() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_5, getBarringInfo) {
+TEST_P(RadioHidlTest_v1_5, getBarringInfo) {
serial = GetRandomSerialNumber();
Return<void> res = radio_v1_5->getBarringInfo(serial);
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
index a5d236d..7313de4 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
@@ -17,19 +17,7 @@
#include <radio_hidl_hal_utils_v1_5.h>
void RadioHidlTest_v1_5::SetUp() {
- radio_v1_5 = ::testing::VtsHalHidlTargetTestBase::getService<
- ::android::hardware::radio::V1_5::IRadio>(
- RadioHidlEnvironment::Instance()
- ->getServiceName<::android::hardware::radio::V1_5::IRadio>(
- hidl_string(RADIO_SERVICE_NAME)));
- if (radio_v1_5 == NULL) {
- sleep(60);
- radio_v1_5 = ::testing::VtsHalHidlTargetTestBase::getService<
- ::android::hardware::radio::V1_5::IRadio>(
- RadioHidlEnvironment::Instance()
- ->getServiceName<::android::hardware::radio::V1_5::IRadio>(
- hidl_string(RADIO_SERVICE_NAME)));
- }
+ radio_v1_5 = android::hardware::radio::V1_5::IRadio::getService(GetParam());
ASSERT_NE(nullptr, radio_v1_5.get());
radioRsp_v1_5 = new (std::nothrow) RadioResponse_v1_5(*this);
@@ -48,14 +36,12 @@
EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
- ::testing::VtsHalHidlTargetTestBase::getService<
- ::android::hardware::radio::config::V1_1::IRadioConfig>();
-
- /* Enforce Vts tesing with RadioConfig is existed. */
+ ::android::hardware::radio::config::V1_1::IRadioConfig::getService();
+ /* Enforce Vts testing with RadioConfig is existed. */
ASSERT_NE(nullptr, radioConfig.get());
/* Enforce Vts Testing with Sim Status Present only. */
- EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.cardState);
+ EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
}
/*
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 a7c1cdc..6a369cc 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
@@ -14,10 +14,14 @@
* limitations under the License.
*/
+#pragma once
+
#include <android-base/logging.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/Log.h>
#include <chrono>
#include <condition_variable>
#include <mutex>
@@ -51,7 +55,7 @@
#define RADIO_SERVICE_NAME "slot1"
class RadioHidlTest_v1_5;
-extern ::android::hardware::radio::V1_4::CardStatus cardStatus;
+extern ::android::hardware::radio::V1_5::CardStatus cardStatus;
/* Callback class for radio response v1_5 */
class RadioResponse_v1_5 : public ::android::hardware::radio::V1_5::IRadioResponse {
@@ -552,6 +556,10 @@
const RadioResponseInfo& info,
const android::hardware::radio::V1_5::SetupDataCallResult& dcResponse);
+ Return<void> getDataCallListResponse_1_5(
+ const RadioResponseInfo& info,
+ const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& dcResponse);
+
Return<void> setInitialAttachApnResponse_1_5(const RadioResponseInfo& info);
Return<void> setDataProfileResponse_1_5(const RadioResponseInfo& info);
@@ -587,6 +595,10 @@
Return<void> supplySimDepersonalizationResponse(
const RadioResponseInfo& info,
::android::hardware::radio::V1_5::PersoSubstate persoType, int32_t remainingRetries);
+
+ Return<void> getIccCardStatusResponse_1_5(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_5::CardStatus& card_status);
};
/* Callback class for radio indication */
@@ -610,6 +622,10 @@
const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::CellInfo>&
records);
+ Return<void> dataCallListChanged_1_5(
+ RadioIndicationType type,
+ const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& dcList);
+
/* 1.4 Api */
Return<void> currentEmergencyNumberList(
RadioIndicationType type,
@@ -799,24 +815,8 @@
/*barringInfos*/);
};
-// Test environment for Radio HIDL HAL.
-class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static RadioHidlEnvironment* Instance() {
- static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
- return instance;
- }
- virtual void registerTestServices() override {
- registerTestService<::android::hardware::radio::V1_5::IRadio>();
- }
-
- private:
- RadioHidlEnvironment() {}
-};
-
// The main test class for Radio HIDL.
-class RadioHidlTest_v1_5 : public ::testing::VtsHalHidlTargetTestBase {
+class RadioHidlTest_v1_5 : public ::testing::TestWithParam<std::string> {
protected:
std::mutex mtx_;
std::condition_variable cv_;
diff --git a/radio/1.5/vts/functional/radio_indication.cpp b/radio/1.5/vts/functional/radio_indication.cpp
index d448a22..1e5ce16 100644
--- a/radio/1.5/vts/functional/radio_indication.cpp
+++ b/radio/1.5/vts/functional/radio_indication.cpp
@@ -18,6 +18,46 @@
RadioIndication_v1_5::RadioIndication_v1_5(RadioHidlTest_v1_5& parent) : parent_v1_5(parent) {}
+/* 1.5 Apis */
+Return<void> RadioIndication_v1_5::uiccApplicationsEnablementChanged(RadioIndicationType /*type*/,
+ bool /*enabled*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_5::registrationFailed(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+ const hidl_string& /*chosenPlmn*/,
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_5::Domain> /*domain*/,
+ int32_t /*causeCode*/, int32_t /*additionalCauseCode*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_5::barringInfoChanged(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+ const hidl_vec<::android::hardware::radio::V1_5::BarringInfo>& /*barringInfos*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_5::networkScanResult_1_5(
+ RadioIndicationType /*type*/,
+ const ::android::hardware::radio::V1_5::NetworkScanResult& /*result*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_5::cellInfoList_1_5(
+ RadioIndicationType /*type*/,
+ const hidl_vec<::android::hardware::radio::V1_5::CellInfo>& /*records*/) {
+ return Void();
+}
+
+Return<void> RadioIndication_v1_5::dataCallListChanged_1_5(
+ RadioIndicationType /*type*/,
+ const hidl_vec<android::hardware::radio::V1_5::SetupDataCallResult>& /*dcList*/) {
+ return Void();
+}
+
/* 1.4 Apis */
Return<void> RadioIndication_v1_5::currentPhysicalChannelConfigs_1_4(
RadioIndicationType /*type*/,
@@ -328,38 +368,3 @@
const ::android::hardware::hidl_string& /*reason*/) {
return Void();
}
-
-Return<void> RadioIndication_v1_5::uiccApplicationsEnablementChanged(RadioIndicationType /*type*/,
- bool /*enabled*/) {
- return Void();
-}
-
-Return<void> RadioIndication_v1_5::registrationFailed(
- RadioIndicationType /*type*/,
- const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
- const ::android::hardware::hidl_string& /*chosenPlmn*/,
- ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_5::Domain> /*domain*/,
- int32_t /*causeCode*/, int32_t /*additionalCauseCode*/) {
- return Void();
-}
-
-Return<void> RadioIndication_v1_5::barringInfoChanged(
- RadioIndicationType /*type*/,
- const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
- const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
- /*barringInfos*/) {
- return Void();
-}
-
-Return<void> RadioIndication_v1_5::networkScanResult_1_5(
- RadioIndicationType /*type*/,
- const ::android::hardware::radio::V1_5::NetworkScanResult& /*result*/) {
- return Void();
-}
-
-Return<void> RadioIndication_v1_5::cellInfoList_1_5(
- RadioIndicationType /*type*/,
- const ::android::hardware::hidl_vec<
- ::android::hardware::radio::V1_5::CellInfo>& /*records*/) {
- return Void();
-}
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index e4f9ce8..8cbb2d0 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -16,7 +16,7 @@
#include <radio_hidl_hal_utils_v1_5.h>
-::android::hardware::radio::V1_4::CardStatus cardStatus;
+::android::hardware::radio::V1_5::CardStatus cardStatus;
RadioResponse_v1_5::RadioResponse_v1_5(RadioHidlTest_v1_5& parent) : parent_v1_5(parent) {}
@@ -829,9 +829,8 @@
Return<void> RadioResponse_v1_5::getIccCardStatusResponse_1_4(
const RadioResponseInfo& info,
- const ::android::hardware::radio::V1_4::CardStatus& card_status) {
+ const ::android::hardware::radio::V1_4::CardStatus& /*card_status*/) {
rspInfo = info;
- cardStatus = card_status;
parent_v1_5.notify(info.serial);
return Void();
}
@@ -944,6 +943,14 @@
return Void();
}
+Return<void> RadioResponse_v1_5::getDataCallListResponse_1_5(
+ const RadioResponseInfo& info,
+ const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& /* dcResponse */) {
+ rspInfo = info;
+ parent_v1_5.notify(info.serial);
+ return Void();
+}
+
Return<void> RadioResponse_v1_5::setInitialAttachApnResponse_1_5(const RadioResponseInfo& info) {
rspInfo = info;
parent_v1_5.notify(info.serial);
@@ -1021,3 +1028,12 @@
int32_t /*remainingRetries*/) {
return Void();
}
+
+Return<void> RadioResponse_v1_5::getIccCardStatusResponse_1_5(
+ const RadioResponseInfo& info,
+ const ::android::hardware::radio::V1_5::CardStatus& card_status) {
+ rspInfo = info;
+ cardStatus = card_status;
+ parent_v1_5.notify(info.serial);
+ return Void();
+}
diff --git a/rebootescrow/aidl/default/HadamardUtils.cpp b/rebootescrow/aidl/default/HadamardUtils.cpp
index d2422b9..adb2010 100644
--- a/rebootescrow/aidl/default/HadamardUtils.cpp
+++ b/rebootescrow/aidl/default/HadamardUtils.cpp
@@ -16,8 +16,6 @@
#include <HadamardUtils.h>
-#include <limits>
-
#include <android-base/logging.h>
namespace aidl {
@@ -92,6 +90,31 @@
return result;
}
+// Constant-time conditional copy, to fix b/146520538
+// ctl must be 0 or 1; we do the copy if it's 1.
+static void CondCopy(uint32_t ctl, void* dest, const void* src, size_t len) {
+ const auto cdest = reinterpret_cast<uint8_t*>(dest);
+ const auto csrc = reinterpret_cast<const uint8_t*>(src);
+ for (size_t i = 0; i < len; i++) {
+ const uint32_t d = cdest[i];
+ const uint32_t s = csrc[i];
+ cdest[i] = d ^ (-ctl & (s ^ d));
+ }
+}
+
+struct CodewordWinner {
+ uint16_t codeword;
+ int32_t score;
+};
+
+// Replace dest with src if it has a higher score
+static void CopyWinner(CodewordWinner* dest, const CodewordWinner& src) {
+ // Scores are between - 2^15 and 2^15, so taking the difference won't
+ // overflow; we use the sign bit of the difference here.
+ CondCopy(static_cast<uint32_t>(dest->score - src.score) >> 31, dest, &src,
+ sizeof(CodewordWinner));
+}
+
// Decode a single codeword. Because of the way codewords are striped together
// this takes the entire input, plus an offset telling it which word to decode.
static uint16_t DecodeWord(size_t word, const std::vector<uint8_t>& encoded) {
@@ -118,20 +141,15 @@
}
}
}
- auto hiscore = std::numeric_limits<int32_t>::min();
- uint16_t winner;
- // TODO(b/146520538): this needs to be constant time
+ // -ENCODE_LENGTH is least possible score, so start one less than that
+ auto best = CodewordWinner{0, -static_cast<int32_t>(ENCODE_LENGTH + 1)};
+ // For every possible codeword value, look at its score, and replace best if it's higher,
+ // in constant time.
for (size_t i = 0; i < ENCODE_LENGTH; i++) {
- if (scores[i] > hiscore) {
- winner = i;
- hiscore = scores[i];
-
- } else if (-scores[i] > hiscore) {
- winner = i | (1 << CODE_K);
- hiscore = -scores[i];
- }
+ CopyWinner(&best, CodewordWinner{static_cast<uint16_t>(i), scores[i]});
+ CopyWinner(&best, CodewordWinner{static_cast<uint16_t>(i | (1 << CODE_K)), -scores[i]});
}
- return winner;
+ return best.codeword;
}
std::vector<uint8_t> DecodeKey(const std::vector<uint8_t>& shuffled) {
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
index b41730b..1af6d0b 100644
--- a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -2,6 +2,6 @@
interface android.hardware.sensors@1.0::ISensors default
class hal
user system
- group system wakelock uhid
+ group system wakelock uhid context_hub
capabilities BLOCK_SUSPEND
rlimit rtprio 10 10
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
index 1e5e886..aca6961 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -25,6 +25,13 @@
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorInfo;
+void SensorsHidlEnvironmentV1_0::HidlTearDown() {
+ mStopThread = true;
+ if (mPollThread.joinable()) {
+ mPollThread.detach();
+ }
+}
+
bool SensorsHidlEnvironmentV1_0::resetHal() {
// wait upto 100ms * 10 = 1s for hidl service.
constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
@@ -103,18 +110,23 @@
ALOGD("polling thread start");
while (!stop) {
- env->sensors->poll(
- 64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
- if (result != Result::OK ||
- (events.size() == 0 && dynamicSensorsAdded.size() == 0) || stop) {
- stop = true;
- return;
- }
+ if (!env->sensors
+ ->poll(64,
+ [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+ if (result != Result::OK ||
+ (events.size() == 0 && dynamicSensorsAdded.size() == 0) ||
+ stop) {
+ stop = true;
+ return;
+ }
- for (const auto& e : events) {
- env->addEvent(e);
- }
- });
+ for (const auto& e : events) {
+ env->addEvent(e);
+ }
+ })
+ .isOk()) {
+ break;
+ }
}
ALOGD("polling thread end");
}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
index 485ed1e..168777d 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -32,6 +32,8 @@
class SensorsHidlEnvironmentV1_0
: public SensorsHidlEnvironmentBase<::android::hardware::sensors::V1_0::Event> {
public:
+ void HidlTearDown() override;
+
using Event = ::android::hardware::sensors::V1_0::Event;
SensorsHidlEnvironmentV1_0(const std::string& service_name)
: SensorsHidlEnvironmentBase(service_name) {}
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 24c475c..7213b44 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -13,14 +13,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_defaults {
- name: "android.hardware.sensors@2.0-multihal-defaults",
- header_libs: [
- "android.hardware.sensors@2.0-multihal.header",
+cc_binary {
+ name: "android.hardware.sensors@2.0-service.multihal",
+ defaults: [
+ "hidl_defaults",
],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "service.cpp",
+ ],
+ init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
+ vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
shared_libs: [
- "android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
+ "android.hardware.sensors@2.0-ScopedWakelock",
"libbase",
"libcutils",
"libfmq",
@@ -29,66 +36,5 @@
"libpower",
"libutils",
],
- cflags: ["-DLOG_TAG=\"SensorsMultiHal\""],
-}
-
-cc_binary {
- name: "android.hardware.sensors@2.0-service.multihal",
- defaults: [
- "hidl_defaults",
- "android.hardware.sensors@2.0-multihal-defaults",
- ],
- vendor: true,
- relative_install_path: "hw",
- srcs: [
- "service.cpp",
- "HalProxy.cpp",
- ],
- init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
- vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
- shared_libs: ["android.hardware.sensors@2.0-ScopedWakelock"],
-}
-
-cc_library_headers {
- name: "android.hardware.sensors@2.0-multihal.header",
- vendor_available: true,
- export_include_dirs: ["include"],
-}
-
-cc_library_shared {
- name: "android.hardware.sensors@2.0-ScopedWakelock",
- defaults: [
- "hidl_defaults",
- "android.hardware.sensors@2.0-multihal-defaults",
- ],
- srcs: [
- "ScopedWakelock.cpp",
- ],
- vendor_available: true,
- export_header_lib_headers: [
- "android.hardware.sensors@2.0-multihal.header",
- ],
-}
-
-// The below targets should only be used for testing.
-cc_test_library {
- name: "android.hardware.sensors@2.0-HalProxy",
- defaults: [
- "hidl_defaults",
- "android.hardware.sensors@2.0-multihal-defaults",
- ],
- vendor_available: true,
- srcs: [
- "HalProxy.cpp",
- ],
- export_header_lib_headers: [
- "android.hardware.sensors@2.0-multihal.header",
- ],
- export_shared_lib_headers: [
- "android.hardware.sensors@2.0-ScopedWakelock",
- ],
- shared_libs: [
- "libutils",
- "android.hardware.sensors@2.0-ScopedWakelock",
- ],
+ static_libs: ["android.hardware.sensors@2.X-multihal"],
}
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 8895350..a0d436f 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -16,6 +16,261 @@
#include "VtsHalSensorsV2_XTargetTest.h"
+// Test if sensor hal can do UI speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
+ testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(200),
+ std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do normal speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
+ testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(20),
+ std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do game speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
+ testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(5),
+ std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do UI speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
+ testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(200),
+ std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do normal speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
+ testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(20),
+ std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do game speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
+ testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(5),
+ std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do UI speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
+ testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(200),
+ std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do normal speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
+ testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(20),
+ std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do game speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
+ testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(5),
+ std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER);
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE);
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD);
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do accelerometer batching properly
+TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
+ testBatchingOperation(SensorTypeVersion::ACCELEROMETER);
+}
+
+// Test if sensor hal can do gyroscope batching properly
+TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
+ testBatchingOperation(SensorTypeVersion::GYROSCOPE);
+}
+
+// Test if sensor hal can do magnetometer batching properly
+TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
+ testBatchingOperation(SensorTypeVersion::MAGNETIC_FIELD);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at normal rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+ RateLevel::NORMAL, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at fast rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+ RateLevel::FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at very fast rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+ RateLevel::VERY_FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at normal rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
+ RateLevel::NORMAL, mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at fast rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
+ mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at very fast rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
+ RateLevel::VERY_FAST, mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for mag sensor at normal rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+ RateLevel::NORMAL, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at fast rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+ RateLevel::FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at very fast rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+ RateLevel::VERY_FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for accel sensor at normal rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+ RateLevel::NORMAL, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at fast rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+ RateLevel::FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at very fast rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+ RateLevel::VERY_FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at normal rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
+ RateLevel::NORMAL, mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at fast rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
+ mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at very fast rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
+ RateLevel::VERY_FAST, mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for mag sensor at normal rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+ RateLevel::NORMAL, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at fast rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+ RateLevel::FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at very fast rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+ RateLevel::VERY_FAST, NullChecker<EventType>());
+}
+
+TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
+ SensorInfoType sensor;
+ SharedMemType memType;
+ RateLevel rate;
+ if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
+ return;
+ }
+
+ // Verify that an invalid channel handle produces a BAD_VALUE result
+ configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) {
+ ASSERT_EQ(result, Result::BAD_VALUE);
+ });
+}
+
+TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
+ constexpr size_t kNumEvents = 1;
+ constexpr size_t kMemSize = kNumEvents * kEventSize;
+
+ SensorInfoType sensor;
+ SharedMemType memType;
+ RateLevel rate;
+
+ if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
+ return;
+ }
+
+ std::shared_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem(
+ SensorsTestSharedMemory<SensorTypeVersion, EventType>::create(memType, kMemSize));
+ ASSERT_NE(mem, nullptr);
+
+ int32_t directChannelHandle = 0;
+ registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
+ ASSERT_EQ(result, Result::OK);
+ directChannelHandle = channelHandle;
+ });
+
+ // Configure the channel and expect success
+ configDirectReport(
+ sensor.sensorHandle, directChannelHandle, rate,
+ [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
+
+ // Call initialize() via the environment setup to cause the HAL to re-initialize
+ // Clear the active direct connections so they are not stopped during TearDown
+ auto handles = mDirectChannelHandles;
+ mDirectChannelHandles.clear();
+ getEnvironment()->HidlTearDown();
+ getEnvironment()->HidlSetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if resetting the environment failed
+ }
+
+ // Attempt to configure the direct channel and expect it to fail
+ configDirectReport(
+ sensor.sensorHandle, directChannelHandle, rate,
+ [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
+
+ // Restore original handles, though they should already be deactivated
+ mDirectChannelHandles = handles;
+}
+
TEST_P(SensorsHidlTest, SensorListDoesntContainInvalidType) {
getSensors()->getSensorsList([&](const auto& list) {
const size_t count = list.size();
@@ -26,6 +281,21 @@
});
}
+TEST_P(SensorsHidlTest, FlushNonexistentSensor) {
+ SensorInfoType sensor;
+ std::vector<SensorInfoType> sensors = getNonOneShotSensors();
+ if (sensors.size() == 0) {
+ sensors = getOneShotSensors();
+ if (sensors.size() == 0) {
+ return;
+ }
+ }
+ sensor = sensors.front();
+ sensor.sensorHandle = getInvalidSensorHandle();
+ runSingleFlushTest(std::vector<SensorInfoType>{sensor}, false /* activateSensor */,
+ 0 /* expectedFlushCount */, Result::BAD_VALUE);
+}
+
INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
android::hardware::sensors::V2_0::ISensors::descriptor)),
diff --git a/sensors/common/default/2.X/multihal/Android.bp b/sensors/common/default/2.X/multihal/Android.bp
new file mode 100644
index 0000000..2b4b3bf
--- /dev/null
+++ b/sensors/common/default/2.X/multihal/Android.bp
@@ -0,0 +1,84 @@
+//
+// 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_defaults {
+ name: "android.hardware.sensors@2.X-multihal-defaults",
+ header_libs: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+ shared_libs: [
+ "android.hardware.sensors@1.0",
+ "android.hardware.sensors@2.0",
+ "libbase",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "liblog",
+ "libpower",
+ "libutils",
+ ],
+ cflags: ["-DLOG_TAG=\"SensorsMultiHal\""],
+}
+
+cc_library_headers {
+ name: "android.hardware.sensors@2.0-multihal.header",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+}
+
+cc_library_static {
+ name: "android.hardware.sensors@2.X-multihal",
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.X-multihal-defaults",
+ ],
+ srcs: [
+ "HalProxy.cpp",
+ ],
+ vendor_available: true,
+ export_header_lib_headers: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.sensors@2.0-ScopedWakelock",
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.X-multihal-defaults",
+ ],
+ srcs: [
+ "ScopedWakelock.cpp",
+ ],
+ vendor_available: true,
+ export_header_lib_headers: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+}
+
+cc_test_library {
+ name: "android.hardware.sensors@2.0-ScopedWakelock.testlib",
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.X-multihal-defaults",
+ ],
+ srcs: [
+ "ScopedWakelock.cpp",
+ ],
+ vendor_available: true,
+ export_header_lib_headers: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+}
diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
similarity index 100%
rename from sensors/2.0/multihal/HalProxy.cpp
rename to sensors/common/default/2.X/multihal/HalProxy.cpp
diff --git a/sensors/2.0/multihal/ScopedWakelock.cpp b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
similarity index 100%
rename from sensors/2.0/multihal/ScopedWakelock.cpp
rename to sensors/common/default/2.X/multihal/ScopedWakelock.cpp
diff --git a/sensors/2.0/multihal/include/HalProxy.h b/sensors/common/default/2.X/multihal/include/HalProxy.h
similarity index 100%
rename from sensors/2.0/multihal/include/HalProxy.h
rename to sensors/common/default/2.X/multihal/include/HalProxy.h
diff --git a/sensors/2.0/multihal/include/ScopedWakelock.h b/sensors/common/default/2.X/multihal/include/ScopedWakelock.h
similarity index 100%
rename from sensors/2.0/multihal/include/ScopedWakelock.h
rename to sensors/common/default/2.X/multihal/include/ScopedWakelock.h
diff --git a/sensors/2.0/multihal/include/SubHal.h b/sensors/common/default/2.X/multihal/include/SubHal.h
similarity index 100%
rename from sensors/2.0/multihal/include/SubHal.h
rename to sensors/common/default/2.X/multihal/include/SubHal.h
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
similarity index 74%
rename from sensors/2.0/multihal/tests/Android.bp
rename to sensors/common/default/2.X/multihal/tests/Android.bp
index a9feaf7..afb63cc 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -14,7 +14,7 @@
// limitations under the License.
cc_defaults {
- name: "android.hardware.sensors@2.0-fakesubhal-defaults",
+ name: "android.hardware.sensors@2.X-fakesubhal-defaults",
srcs: [
"fake_subhal/*.cpp",
],
@@ -35,7 +35,7 @@
"libutils",
],
static_libs: [
- "android.hardware.sensors@2.0-HalProxy",
+ "android.hardware.sensors@2.X-multihal",
],
cflags: [
"-DLOG_TAG=\"FakeSubHal\"",
@@ -43,9 +43,9 @@
}
cc_library {
- name: "android.hardware.sensors@2.0-fakesubhal-config1",
+ name: "android.hardware.sensors@2.X-fakesubhal-config1",
vendor: true,
- defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"],
+ defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
"-DSUPPORT_CONTINUOUS_SENSORS",
"-DSUB_HAL_NAME=\"FakeSubHal-Continuous\"",
@@ -53,9 +53,9 @@
}
cc_library {
- name: "android.hardware.sensors@2.0-fakesubhal-config2",
+ name: "android.hardware.sensors@2.X-fakesubhal-config2",
vendor: true,
- defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"],
+ defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
"-DSUPPORT_ON_CHANGE_SENSORS",
"-DSUB_HAL_NAME=\"FakeSubHal-OnChange\"",
@@ -63,9 +63,9 @@
}
cc_test_library {
- name: "android.hardware.sensors@2.0-fakesubhal-unittest",
+ name: "android.hardware.sensors@2.X-fakesubhal-unittest",
vendor_available: true,
- defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"],
+ defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
"-DSUPPORT_ON_CHANGE_SENSORS",
"-DSUPPORT_CONTINUOUS_SENSORS",
@@ -74,17 +74,17 @@
}
cc_test {
- name: "android.hardware.sensors@2.0-halproxy-unit-tests",
+ name: "android.hardware.sensors@2.X-halproxy-unit-tests",
srcs: ["HalProxy_test.cpp"],
vendor: true,
static_libs: [
- "android.hardware.sensors@2.0-HalProxy",
- "android.hardware.sensors@2.0-fakesubhal-unittest",
+ "android.hardware.sensors@2.0-ScopedWakelock.testlib",
+ "android.hardware.sensors@2.X-multihal",
+ "android.hardware.sensors@2.X-fakesubhal-unittest",
],
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
- "android.hardware.sensors@2.0-ScopedWakelock",
"libbase",
"libcutils",
"libfmq",
diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
similarity index 95%
rename from sensors/2.0/multihal/tests/HalProxy_test.cpp
rename to sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
index 1fd35d1..4633a75 100644
--- a/sensors/2.0/multihal/tests/HalProxy_test.cpp
+++ b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
@@ -724,6 +724,45 @@
EXPECT_EQ(eventOut.sensorHandle, (subhal2Index << 24) | sensorHandleToPost);
}
+TEST(HalProxyTest, FillAndDrainPendingQueueTest) {
+ constexpr size_t kQueueSize = 5;
+ // TODO: Make this constant linked to same limit in HalProxy.h
+ constexpr size_t kMaxPendingQueueSize = 100000;
+ AllSensorsSubHal subhal;
+ std::vector<ISensorsSubHal*> subHals{&subhal};
+
+ std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
+ ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ EventFlag* eventQueueFlag;
+ EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag);
+ HalProxy proxy(subHals);
+ proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+ // Fill pending queue
+ std::vector<Event> events = makeMultipleAccelerometerEvents(kQueueSize);
+ subhal.postEvents(events, false);
+ events = makeMultipleAccelerometerEvents(kMaxPendingQueueSize);
+ subhal.postEvents(events, false);
+
+ // Drain pending queue
+ for (int i = 0; i < kMaxPendingQueueSize + kQueueSize; i += kQueueSize) {
+ ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+ }
+
+ // Put one event on pending queue
+ events = makeMultipleAccelerometerEvents(kQueueSize);
+ subhal.postEvents(events, false);
+ events = {makeAccelerometerEvent()};
+ subhal.postEvents(events, false);
+
+ // Read out to make room for one event on pending queue to write to FMQ
+ ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+
+ // Should be able to read that last event off queue
+ EXPECT_TRUE(readEventsOutOfQueue(1, eventQueue, eventQueueFlag));
+}
+
// Helper implementations follow
void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
const std::vector<SensorInfo>& subHalSensorsList) {
diff --git a/sensors/2.0/multihal/tests/fake_subhal/README b/sensors/common/default/2.X/multihal/tests/fake_subhal/README
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/README
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/README
diff --git a/sensors/2.0/multihal/tests/fake_subhal/Sensor.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/Sensor.cpp
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
diff --git a/sensors/2.0/multihal/tests/fake_subhal/Sensor.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/Sensor.h
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp
diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 53ed259..745ab2d 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -469,201 +469,6 @@
ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
}
-// Test if sensor hal can do UI speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
- testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(200),
- std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do normal speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
- testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(20),
- std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do game speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
- testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(5),
- std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do UI speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
- testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(200),
- std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do normal speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
- testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(20),
- std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do game speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
- testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(5),
- std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do UI speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
- testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(200),
- std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do normal speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
- testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(20),
- std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do game speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
- testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(5),
- std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
- testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER);
- testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
- testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE);
- testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
- testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD);
- testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do accelerometer batching properly
-TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
- testBatchingOperation(SensorTypeVersion::ACCELEROMETER);
-}
-
-// Test if sensor hal can do gyroscope batching properly
-TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
- testBatchingOperation(SensorTypeVersion::GYROSCOPE);
-}
-
-// Test if sensor hal can do magnetometer batching properly
-TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
- testBatchingOperation(SensorTypeVersion::MAGNETIC_FIELD);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at normal rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
- RateLevel::NORMAL, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at fast rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
- RateLevel::FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at very fast rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
- RateLevel::VERY_FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at normal rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
- RateLevel::NORMAL, mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at fast rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
- mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at very fast rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
- RateLevel::VERY_FAST, mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for mag sensor at normal rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
- RateLevel::NORMAL, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with ashmem for mag sensor at fast rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
- RateLevel::FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with ashmem for mag sensor at very fast rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
- RateLevel::VERY_FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for accel sensor at normal rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
- RateLevel::NORMAL, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for accel sensor at fast rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
- RateLevel::FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for accel sensor at very fast rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
- RateLevel::VERY_FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at normal rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
- RateLevel::NORMAL, mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at fast rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
- mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at very fast rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
- RateLevel::VERY_FAST, mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for mag sensor at normal rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
- RateLevel::NORMAL, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for mag sensor at fast rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
- RateLevel::FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for mag sensor at very fast rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
- RateLevel::VERY_FAST, NullChecker<EventType>());
-}
-
void SensorsHidlTest::activateAllSensors(bool enable) {
for (const SensorInfoType& sensorInfo : getSensorsList()) {
if (isValidType(sensorInfo.type)) {
@@ -829,21 +634,6 @@
Result::BAD_VALUE);
}
-TEST_P(SensorsHidlTest, FlushNonexistentSensor) {
- SensorInfoType sensor;
- std::vector<SensorInfoType> sensors = getNonOneShotSensors();
- if (sensors.size() == 0) {
- sensors = getOneShotSensors();
- if (sensors.size() == 0) {
- return;
- }
- }
- sensor = sensors.front();
- sensor.sensorHandle = getInvalidSensorHandle();
- runSingleFlushTest(std::vector<SensorInfoType>{sensor}, false /* activateSensor */,
- 0 /* expectedFlushCount */, Result::BAD_VALUE);
-}
-
TEST_P(SensorsHidlTest, Batch) {
if (getSensorsList().size() == 0) {
return;
@@ -1124,63 +914,3 @@
}
return found;
}
-
-TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
- SensorInfoType sensor;
- SharedMemType memType;
- RateLevel rate;
- if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
- return;
- }
-
- // Verify that an invalid channel handle produces a BAD_VALUE result
- configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) {
- ASSERT_EQ(result, Result::BAD_VALUE);
- });
-}
-
-TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
- constexpr size_t kNumEvents = 1;
- constexpr size_t kMemSize = kNumEvents * kEventSize;
-
- SensorInfoType sensor;
- SharedMemType memType;
- RateLevel rate;
-
- if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
- return;
- }
-
- std::shared_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem(
- SensorsTestSharedMemory<SensorTypeVersion, EventType>::create(memType, kMemSize));
- ASSERT_NE(mem, nullptr);
-
- int32_t directChannelHandle = 0;
- registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
- ASSERT_EQ(result, Result::OK);
- directChannelHandle = channelHandle;
- });
-
- // Configure the channel and expect success
- configDirectReport(
- sensor.sensorHandle, directChannelHandle, rate,
- [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
-
- // Call initialize() via the environment setup to cause the HAL to re-initialize
- // Clear the active direct connections so they are not stopped during TearDown
- auto handles = mDirectChannelHandles;
- mDirectChannelHandles.clear();
- getEnvironment()->HidlTearDown();
- getEnvironment()->HidlSetUp();
- if (HasFatalFailure()) {
- return; // Exit early if resetting the environment failed
- }
-
- // Attempt to configure the direct channel and expect it to fail
- configDirectReport(
- sensor.sensorHandle, directChannelHandle, rate,
- [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
-
- // Restore original handles, though they should already be deactivated
- mDirectChannelHandles = handles;
-}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
index 781427d..19dfbe5 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -46,12 +46,7 @@
std::this_thread::sleep_for(std::chrono::seconds(3));
}
- virtual void HidlTearDown() {
- mStopThread = true;
- if (mPollThread.joinable()) {
- mPollThread.join();
- }
- }
+ virtual void HidlTearDown() = 0;
// Get and clear all events collected so far (like "cat" shell command).
// If output is nullptr, it clears all collected events.
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index dd2f8a6..7e206a7 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -81,6 +81,10 @@
Return<Result> Frontend::scan(const FrontendSettings& /* settings */, FrontendScanType /* type */) {
ALOGV("%s", __FUNCTION__);
+ FrontendScanMessage msg;
+ msg.isLocked(true);
+ mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
+
return Result::SUCCESS;
}
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 820c58c..f693e7c 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,8 @@
#include <iostream>
#include <map>
+#include "VtsHalTvTunerV1_0TestConfigurations.h"
+
#define WAIT_TIMEOUT 3000000000
#define WAIT_TIMEOUT_data_ready 3000000000 * 4
@@ -84,9 +86,11 @@
using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
using android::hardware::tv::tuner::V1_0::FrontendEventType;
using android::hardware::tv::tuner::V1_0::FrontendId;
+using android::hardware::tv::tuner::V1_0::FrontendInfo;
using android::hardware::tv::tuner::V1_0::FrontendInnerFec;
using android::hardware::tv::tuner::V1_0::FrontendScanMessage;
using android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using android::hardware::tv::tuner::V1_0::FrontendScanType;
using android::hardware::tv::tuner::V1_0::FrontendSettings;
using android::hardware::tv::tuner::V1_0::IDemux;
using android::hardware::tv::tuner::V1_0::IDescrambler;
@@ -103,6 +107,8 @@
using android::hardware::tv::tuner::V1_0::RecordStatus;
using android::hardware::tv::tuner::V1_0::Result;
+using ::testing::AssertionResult;
+
namespace {
using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
@@ -150,11 +156,7 @@
// const uint16_t FMQ_SIZE_4K = 0x1000;
const uint32_t FMQ_SIZE_1M = 0x100000;
const uint32_t FMQ_SIZE_16M = 0x1000000;
-
-struct FilterConf {
- DemuxFilterType type;
- DemuxFilterSettings setting;
-};
+const uint8_t FRONTEND_EVENT_CALLBACK_WAIT_COUNT = 4;
enum FilterEventType : uint8_t {
UNDEFINED,
@@ -172,6 +174,7 @@
PlaybackSettings setting;
};
+/******************************** Start FrontendCallback **********************************/
class FrontendCallback : public IFrontendCallback {
public:
virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
@@ -182,28 +185,38 @@
return Void();
}
- virtual Return<void> onScanMessage(FrontendScanMessageType /* type */,
- const FrontendScanMessage& /* message */) override {
+ virtual Return<void> onScanMessage(FrontendScanMessageType type,
+ const FrontendScanMessage& message) override {
android::Mutex::Autolock autoLock(mMsgLock);
+ ALOGD("[vts] scan message. Type: %d", mScanMessageType);
mScanMessageReceived = true;
+ mScanMessageType = type;
+ mScanLockMessageReceived =
+ mScanLockMessageReceived | (type == FrontendScanMessageType::LOCKED);
+ mScanMessage = message;
mMsgCondition.signal();
return Void();
};
- void testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings);
- void testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings);
+ void tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings);
+ void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
+ void scanTestOnMessageLock(sp<IFrontend>& frontend, FrontendSettings settings,
+ FrontendScanType type);
private:
bool mEventReceived = false;
- bool mDiseqcMessageReceived = false;
bool mScanMessageReceived = false;
+ bool mScanLockMessageReceived = false;
FrontendEventType mEventType;
+ FrontendScanMessageType mScanMessageType;
+ FrontendScanMessage mScanMessage;
hidl_vec<uint8_t> mEventMessage;
android::Mutex mMsgLock;
android::Condition mMsgCondition;
+ uint8_t mOnEvenRetry = 0;
};
-void FrontendCallback::testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings) {
+void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
Result result = frontend->tune(settings);
EXPECT_TRUE(result == Result::SUCCESS);
@@ -215,29 +228,77 @@
return;
}
}
+ mEventReceived = false;
}
-void FrontendCallback::testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings) {
+void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
Result result = frontend->tune(settings);
EXPECT_TRUE(result == Result::SUCCESS);
android::Mutex::Autolock autoLock(mMsgLock);
- while (!mDiseqcMessageReceived) {
+wait:
+ while (!mEventReceived) {
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "diseqc message not received within timeout";
+ EXPECT_TRUE(false) << "event not received within timeout";
return;
}
}
+ if (mEventType != FrontendEventType::LOCKED) {
+ ALOGD("[vts] frontend callback event received. Type: %d", mEventType);
+ mEventReceived = false;
+ if (mOnEvenRetry++ < FRONTEND_EVENT_CALLBACK_WAIT_COUNT) {
+ goto wait;
+ }
+ }
+ EXPECT_TRUE(mEventType == FrontendEventType::LOCKED) << "LOCK event not received";
+ mEventReceived = false;
+ mOnEvenRetry = 0;
}
+void FrontendCallback::scanTestOnMessageLock(sp<IFrontend>& frontend, FrontendSettings settings,
+ FrontendScanType type) {
+ Result result = frontend->scan(settings, type);
+ EXPECT_TRUE(result == Result::SUCCESS);
+ android::Mutex::Autolock autoLock(mMsgLock);
+ int messagesCount = 0;
+
+wait:
+ int count = 0;
+ while (!mScanMessageReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ ALOGD("[vts] waiting for scan message callback...");
+ if (count++ > 10) {
+ EXPECT_TRUE(false) << "WAITING TOO LONG!!";
+ return;
+ }
+ }
+ }
+
+ if (mScanMessageType != FrontendScanMessageType::END) {
+ ALOGD("[vts] frontend scan message received. Type: %d", mScanMessageType);
+ mScanMessageReceived = false;
+ if (messagesCount++ > 3) {
+ EXPECT_TRUE(false) << "WAITING ON TOO MANY MSGS!!";
+ return;
+ }
+ goto wait;
+ }
+
+ EXPECT_TRUE(mScanLockMessageReceived) << "scan lock message not received before scan ended";
+ mScanMessageReceived = false;
+ mScanLockMessageReceived = false;
+}
+/******************************** End FrontendCallback **********************************/
+
+/******************************** Start FilterCallback **********************************/
class FilterCallback : public IFilterCallback {
public:
virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override {
android::Mutex::Autolock autoLock(mMsgLock);
// Temprarily we treat the first coming back filter data on the matching pid a success
// once all of the MQ are cleared, means we got all the expected output
- mFilterIdToEvent = filterEvent;
+ mFilterEvent = filterEvent;
readFilterEventData();
mPidFilterOutputCount++;
// mFilterIdToMQ.erase(filterEvent.filterId);
@@ -276,9 +337,9 @@
uint32_t mFilterId;
FilterEventType mFilterEventType;
- std::unique_ptr<FilterMQ> mFilterIdToMQ;
- EventFlag* mFilterIdToMQEventFlag;
- DemuxFilterEvent mFilterIdToEvent;
+ std::unique_ptr<FilterMQ> mFilterMQ;
+ EventFlag* mFilterMQEventFlag;
+ DemuxFilterEvent mFilterEvent;
android::Mutex mMsgLock;
android::Mutex mFilterOutputLock;
@@ -313,10 +374,10 @@
}
void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
- mFilterIdToMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(mFilterIdToMQ);
- EXPECT_TRUE(EventFlag::createEventFlag(mFilterIdToMQ->getEventFlagWord(),
- &mFilterIdToMQEventFlag) == android::OK);
+ mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
+ EXPECT_TRUE(mFilterMQ);
+ EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) ==
+ android::OK);
}
void FilterCallback::updateGoldenOutputMap(string goldenOutputFile) {
@@ -332,7 +393,7 @@
void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
android::Mutex::Autolock autoLock(mFilterOutputLock);
- // Read from mFilterIdToMQ[event.filterId] per event and filter type
+ // Read from mFilterMQ[event.filterId] per event and filter type
// Assemble to filterOutput[filterId]
@@ -345,7 +406,7 @@
bool FilterCallback::readFilterEventData() {
bool result = false;
- DemuxFilterEvent filterEvent = mFilterIdToEvent;
+ DemuxFilterEvent filterEvent = mFilterEvent;
ALOGW("[vts] reading from filter FMQ %d", mFilterId);
// todo separate filter handlers
for (int i = 0; i < filterEvent.events.size(); i++) {
@@ -357,6 +418,7 @@
mDataLength = filterEvent.events[i].pes().dataLength;
break;
case FilterEventType::MEDIA:
+ mDataLength = filterEvent.events[i].media().dataLength;
break;
case FilterEventType::RECORD:
break;
@@ -371,17 +433,19 @@
// match";
mDataOutputBuffer.resize(mDataLength);
- result = mFilterIdToMQ->read(mDataOutputBuffer.data(), mDataLength);
+ result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength);
EXPECT_TRUE(result) << "can't read from Filter MQ";
/*for (int i = 0; i < mDataLength; i++) {
EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
}*/
}
- mFilterIdToMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
return result;
}
+/******************************** End FilterCallback **********************************/
+/******************************** Start DvrCallback **********************************/
class DvrCallback : public IDvrCallback {
public:
virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
@@ -445,11 +509,10 @@
uint16_t mDataLength = 0;
std::vector<uint8_t> mDataOutputBuffer;
- std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterIdToMQ;
+ std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
std::unique_ptr<FilterMQ> mPlaybackMQ;
std::unique_ptr<FilterMQ> mRecordMQ;
- std::map<uint32_t, EventFlag*> mFilterIdToMQEventFlag;
- std::map<uint32_t, DemuxFilterEvent> mFilterIdToEvent;
+ std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
android::Mutex mMsgLock;
android::Mutex mPlaybackThreadLock;
@@ -635,22 +698,32 @@
mRecordThreadRunning = false;
android::Mutex::Autolock autoLock(mRecordThreadLock);
}
+/********************************** End DvrCallback ************************************/
+/***************************** Start Test Implementation ******************************/
class TunerHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
mService = ITuner::getService(GetParam());
ASSERT_NE(mService, nullptr);
+ initFrontendConfig();
+ initFrontendScanConfig();
+ initFilterConfig();
}
sp<ITuner> mService;
protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
static void description(const std::string& description) {
RecordProperty("description", description);
}
sp<IFrontend> mFrontend;
+ FrontendInfo mFrontendInfo;
sp<FrontendCallback> mFrontendCallback;
sp<IDescrambler> mDescrambler;
sp<IDemux> mDemux;
@@ -661,274 +734,165 @@
sp<FilterCallback> mFilterCallback;
sp<DvrCallback> mDvrCallback;
MQDesc mFilterMQDescriptor;
- MQDesc mPlaybackMQDescriptor;
+ MQDesc mDvrMQDescriptor;
MQDesc mRecordMQDescriptor;
vector<uint32_t> mUsedFilterIds;
+ hidl_vec<FrontendId> mFeIds;
uint32_t mDemuxId;
- uint32_t mFilterId;
+ uint32_t mFilterId = -1;
pthread_t mPlaybackshread;
bool mPlaybackThreadRunning;
- ::testing::AssertionResult createFrontend(int32_t frontendId);
- ::testing::AssertionResult tuneFrontend(int32_t frontendId);
- ::testing::AssertionResult stopTuneFrontend(int32_t frontendId);
- ::testing::AssertionResult closeFrontend(int32_t frontendId);
- ::testing::AssertionResult createDemux();
- ::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId,
- FrontendSettings settings);
- ::testing::AssertionResult getPlaybackMQDescriptor();
- ::testing::AssertionResult addPlaybackToDemux(PlaybackSettings setting);
- ::testing::AssertionResult getRecordMQDescriptor();
- ::testing::AssertionResult addRecordToDemux(RecordSettings setting);
- ::testing::AssertionResult addFilterToDemux(DemuxFilterType type, DemuxFilterSettings setting);
- ::testing::AssertionResult getFilterMQDescriptor();
- ::testing::AssertionResult closeDemux();
- ::testing::AssertionResult createDescrambler();
- ::testing::AssertionResult closeDescrambler();
+ AssertionResult getFrontendIds();
+ AssertionResult getFrontendInfo(uint32_t frontendId);
+ AssertionResult openFrontend(uint32_t frontendId);
+ AssertionResult setFrontendCallback();
+ AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
+ AssertionResult stopScanFrontend();
+ AssertionResult tuneFrontend(FrontendConfig config);
+ AssertionResult stopTuneFrontend();
+ AssertionResult closeFrontend();
- ::testing::AssertionResult playbackDataFlowTest(vector<FilterConf> filterConf,
- PlaybackConf playbackConf,
- vector<string> goldenOutputFiles);
- ::testing::AssertionResult recordDataFlowTest(vector<FilterConf> filterConf,
- RecordSettings recordSetting,
- vector<string> goldenOutputFiles);
- ::testing::AssertionResult broadcastDataFlowTest(vector<FilterConf> filterConf,
- vector<string> goldenOutputFiles);
+ AssertionResult openDemux();
+ AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
+ AssertionResult closeDemux();
+
+ AssertionResult openDvrInDemux(DvrType type);
+ AssertionResult configDvr(DvrSettings setting);
+ AssertionResult getDvrMQDescriptor();
+
+ AssertionResult openFilterInDemux(DemuxFilterType type);
+ AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
+ AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
+ AssertionResult getFilterMQDescriptor(uint32_t filterId);
+ AssertionResult startFilter(uint32_t filterId);
+ AssertionResult stopFilter(uint32_t filterId);
+ AssertionResult closeFilter(uint32_t filterId);
+
+ AssertionResult createDescrambler();
+ AssertionResult closeDescrambler();
+
+ AssertionResult playbackDataFlowTest(vector<FilterConfig> filterConf, PlaybackConf playbackConf,
+ vector<string> goldenOutputFiles);
+ AssertionResult recordDataFlowTest(vector<FilterConfig> filterConf,
+ RecordSettings recordSetting,
+ vector<string> goldenOutputFiles);
+ AssertionResult broadcastDataFlowTest(vector<string> goldenOutputFiles);
+
+ FilterEventType getFilterEventType(DemuxFilterType type);
};
-::testing::AssertionResult TunerHidlTest::createFrontend(int32_t frontendId) {
+/*========================== Start Frontend APIs Tests Implementation ==========================*/
+AssertionResult TunerHidlTest::getFrontendIds() {
Result status;
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ mFeIds = frontendIds;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+AssertionResult TunerHidlTest::getFrontendInfo(uint32_t frontendId) {
+ Result status;
+ mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
+ mFrontendInfo = frontendInfo;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult TunerHidlTest::openFrontend(uint32_t frontendId) {
+ Result status;
mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
mFrontend = frontend;
status = result;
});
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
+ return AssertionResult(status == Result::SUCCESS);
+}
+AssertionResult TunerHidlTest::setFrontendCallback() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
mFrontendCallback = new FrontendCallback();
auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
-
- return ::testing::AssertionResult(callbackStatus.isOk());
+ return AssertionResult(callbackStatus.isOk());
}
-::testing::AssertionResult TunerHidlTest::tuneFrontend(int32_t frontendId) {
- if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
+AssertionResult TunerHidlTest::scanFrontend(FrontendConfig config, FrontendScanType type) {
+ EXPECT_TRUE(mFrontendCallback)
+ << "test with openFrontend/setFrontendCallback/getFrontendInfo first.";
- // Frontend Settings for testing
- FrontendSettings frontendSettings;
- FrontendAtscSettings frontendAtscSettings{
- .frequency = 0,
- .modulation = FrontendAtscModulation::UNDEFINED,
- };
- frontendSettings.atsc(frontendAtscSettings);
- mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
+ EXPECT_TRUE(mFrontendInfo.type == config.type)
+ << "FrontendConfig does not match the frontend info of the given id.";
- FrontendDvbtSettings frontendDvbtSettings{
- .frequency = 0,
- };
- frontendSettings.dvbt(frontendDvbtSettings);
- mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
-
- return ::testing::AssertionResult(true);
+ mFrontendCallback->scanTestOnMessageLock(mFrontend, config.settings, type);
+ return AssertionResult(true);
}
-::testing::AssertionResult TunerHidlTest::stopTuneFrontend(int32_t frontendId) {
+AssertionResult TunerHidlTest::stopScanFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
Result status;
- if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
+ status = mFrontend->stopScan();
+ return AssertionResult(status == Result::SUCCESS);
+}
+AssertionResult TunerHidlTest::tuneFrontend(FrontendConfig config) {
+ EXPECT_TRUE(mFrontendCallback)
+ << "test with openFrontend/setFrontendCallback/getFrontendInfo first.";
+
+ EXPECT_TRUE(mFrontendInfo.type == config.type)
+ << "FrontendConfig does not match the frontend info of the given id.";
+
+ mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
+ return AssertionResult(true);
+}
+
+AssertionResult TunerHidlTest::stopTuneFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
+ Result status;
status = mFrontend->stopTune();
- return ::testing::AssertionResult(status == Result::SUCCESS);
+ return AssertionResult(status == Result::SUCCESS);
}
-::testing::AssertionResult TunerHidlTest::closeFrontend(int32_t frontendId) {
+AssertionResult TunerHidlTest::closeFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
Result status;
- if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
status = mFrontend->close();
mFrontend = nullptr;
- return ::testing::AssertionResult(status == Result::SUCCESS);
+ mFrontendCallback = nullptr;
+ return AssertionResult(status == Result::SUCCESS);
}
+/*=========================== End Frontend APIs Tests Implementation ===========================*/
-::testing::AssertionResult TunerHidlTest::createDemux() {
+/*============================ Start Demux APIs Tests Implementation ============================*/
+AssertionResult TunerHidlTest::openDemux() {
Result status;
-
mService->openDemux([&](Result result, uint32_t demuxId, const sp<IDemux>& demux) {
mDemux = demux;
mDemuxId = demuxId;
status = result;
});
- return ::testing::AssertionResult(status == Result::SUCCESS);
+ return AssertionResult(status == Result::SUCCESS);
}
-::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId,
- FrontendSettings settings) {
- Result status;
-
- if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- mFrontendCallback->testOnEvent(mFrontend, settings);
-
- status = mDemux->setFrontendDataSource(frontendId);
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
+AssertionResult TunerHidlTest::setDemuxFrontendDataSource(uint32_t frontendId) {
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
+ auto status = mDemux->setFrontendDataSource(frontendId);
+ return AssertionResult(status.isOk());
}
-::testing::AssertionResult TunerHidlTest::closeDemux() {
- Result status;
- if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- status = mDemux->close();
+AssertionResult TunerHidlTest::closeDemux() {
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ auto status = mDemux->close();
mDemux = nullptr;
- return ::testing::AssertionResult(status == Result::SUCCESS);
+ return AssertionResult(status.isOk());
}
-::testing::AssertionResult TunerHidlTest::createDescrambler() {
+AssertionResult TunerHidlTest::openFilterInDemux(DemuxFilterType type) {
Result status;
-
- mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
- mDescrambler = descrambler;
- status = result;
- });
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
-
- if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- status = mDescrambler->setDemuxSource(mDemuxId);
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
-
- // Test if demux source can be set more than once.
- status = mDescrambler->setDemuxSource(mDemuxId);
- return ::testing::AssertionResult(status == Result::INVALID_STATE);
-}
-
-::testing::AssertionResult TunerHidlTest::closeDescrambler() {
- Result status;
- if (!mDescrambler && createDescrambler() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- status = mDescrambler->close();
- mDescrambler = nullptr;
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::addPlaybackToDemux(PlaybackSettings setting) {
- Result status;
-
- if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Create dvr callback
- mDvrCallback = new DvrCallback();
-
- // Add playback input to the local demux
- mDemux->openDvr(DvrType::PLAYBACK, FMQ_SIZE_1M, mDvrCallback,
- [&](Result result, const sp<IDvr>& dvr) {
- mDvr = dvr;
- status = result;
- });
-
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
-
- DvrSettings dvrSetting;
- dvrSetting.playback(setting);
- status = mDvr->configure(dvrSetting);
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::getPlaybackMQDescriptor() {
- Result status;
-
- if ((!mDemux && createDemux() == ::testing::AssertionFailure()) || !mDvr) {
- return ::testing::AssertionFailure();
- }
-
- mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
- mPlaybackMQDescriptor = dvrMQDesc;
- status = result;
- });
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::addRecordToDemux(RecordSettings setting) {
- Result status;
-
- if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Create dvr callback
- mDvrCallback = new DvrCallback();
-
- // Add playback input to the local demux
- mDemux->openDvr(DvrType::RECORD, FMQ_SIZE_1M, mDvrCallback,
- [&](Result result, const sp<IDvr>& dvr) {
- mDvr = dvr;
- status = result;
- });
-
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
-
- DvrSettings dvrSetting;
- dvrSetting.record(setting);
- status = mDvr->configure(dvrSetting);
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::getRecordMQDescriptor() {
- Result status;
-
- if ((!mDemux && createDemux() == ::testing::AssertionFailure()) || !mDvr) {
- return ::testing::AssertionFailure();
- }
-
- mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
- mRecordMQDescriptor = dvrMQDesc;
- status = result;
- });
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::addFilterToDemux(DemuxFilterType type,
- DemuxFilterSettings setting) {
- Result status;
-
- if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
// Create demux callback
mFilterCallback = new FilterCallback();
@@ -940,21 +904,322 @@
status = result;
});
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
+ if (status == Result::SUCCESS) {
+ mFilterCallback->setFilterEventType(getFilterEventType(type));
}
+ return AssertionResult(status == Result::SUCCESS);
+}
+/*============================ End Demux APIs Tests Implementation ============================*/
+
+/*=========================== Start Filter APIs Tests Implementation ===========================*/
+AssertionResult TunerHidlTest::getNewlyOpenedFilterId(uint32_t& filterId) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
+ EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
+
mFilter->getId([&](Result result, uint32_t filterId) {
mFilterId = filterId;
status = result;
});
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
+ if (status == Result::SUCCESS) {
+ mFilterCallback->setFilterId(mFilterId);
+ mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
+ mFilters[mFilterId] = mFilter;
+ mFilterCallbacks[mFilterId] = mFilterCallback;
+ filterId = mFilterId;
}
- mFilterCallback->setFilterId(mFilterId);
+ return AssertionResult(status == Result::SUCCESS || status == Result::UNAVAILABLE);
+}
+AssertionResult TunerHidlTest::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
+ Result status;
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ status = mFilters[filterId]->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult TunerHidlTest::getFilterMQDescriptor(uint32_t filterId) {
+ Result status;
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
+
+ mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
+ mFilterMQDescriptor = filterMQDesc;
+ status = result;
+ });
+
+ if (status == Result::SUCCESS) {
+ mFilterCallbacks[filterId]->updateFilterMQ(mFilterMQDescriptor);
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult TunerHidlTest::startFilter(uint32_t filterId) {
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ Result status = mFilters[filterId]->start();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult TunerHidlTest::stopFilter(uint32_t filterId) {
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ Result status = mFilters[filterId]->stop();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult TunerHidlTest::closeFilter(uint32_t filterId) {
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ Result status = mFilters[filterId]->close();
+ if (status == Result::SUCCESS) {
+ for (int i = 0; i < mUsedFilterIds.size(); i++) {
+ if (mUsedFilterIds[i] == filterId) {
+ mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
+ break;
+ }
+ }
+ mFilterCallbacks.erase(filterId);
+ mFilters.erase(filterId);
+ }
+ return AssertionResult(status == Result::SUCCESS);
+}
+/*=========================== End Filter APIs Tests Implementation ===========================*/
+
+/*======================== Start Descrambler APIs Tests Implementation ========================*/
+AssertionResult TunerHidlTest::createDescrambler() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
+ mDescrambler = descrambler;
+ status = result;
+ });
+ if (status != Result::SUCCESS) {
+ return failure();
+ }
+
+ status = mDescrambler->setDemuxSource(mDemuxId);
+ if (status != Result::SUCCESS) {
+ return failure();
+ }
+
+ // Test if demux source can be set more than once.
+ status = mDescrambler->setDemuxSource(mDemuxId);
+ return AssertionResult(status == Result::INVALID_STATE);
+}
+
+AssertionResult TunerHidlTest::closeDescrambler() {
+ Result status;
+ if (!mDescrambler && createDescrambler() == failure()) {
+ return failure();
+ }
+
+ status = mDescrambler->close();
+ mDescrambler = nullptr;
+ return AssertionResult(status == Result::SUCCESS);
+}
+/*========================= End Descrambler APIs Tests Implementation =========================*/
+
+/*============================ Start Dvr APIs Tests Implementation ============================*/
+AssertionResult TunerHidlTest::openDvrInDemux(DvrType type) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+ // Create dvr callback
+ mDvrCallback = new DvrCallback();
+
+ mDemux->openDvr(type, FMQ_SIZE_1M, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
+ mDvr = dvr;
+ status = result;
+ });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult TunerHidlTest::configDvr(DvrSettings setting) {
+ Result status = mDvr->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult TunerHidlTest::getDvrMQDescriptor() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+
+ mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+ mDvrMQDescriptor = dvrMQDesc;
+ status = result;
+ });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+/*============================ End Dvr APIs Tests Implementation ============================*/
+
+/*========================== Start Data Flow Tests Implementation ==========================*/
+AssertionResult TunerHidlTest::broadcastDataFlowTest(vector<string> /*goldenOutputFiles*/) {
+ EXPECT_TRUE(mFrontend) << "Test with openFilterInDemux first.";
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mFilterCallback) << "Test with getFilterMQDescriptor first.";
+
+ // Data Verify Module
+ std::map<uint32_t, sp<FilterCallback>>::iterator it;
+ for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
+ it->second->testFilterDataOutput();
+ }
+ return success();
+}
+
+/*
+ * TODO: re-enable the tests after finalizing the test refactoring.
+ */
+/*AssertionResult TunerHidlTest::playbackDataFlowTest(
+ vector<FilterConf> filterConf, PlaybackConf playbackConf,
+ vector<string> \/\*goldenOutputFiles\*\/) {
+ Result status;
+ int filterIdsSize;
+ // Filter Configuration Module
+ for (int i = 0; i < filterConf.size(); i++) {
+ if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
+ failure() ||
+ // TODO use a map to save the FMQs/EvenFlags and pass to callback
+ getFilterMQDescriptor() == failure()) {
+ return failure();
+ }
+ filterIdsSize = mUsedFilterIds.size();
+ mUsedFilterIds.resize(filterIdsSize + 1);
+ mUsedFilterIds[filterIdsSize] = mFilterId;
+ mFilters[mFilterId] = mFilter;
+ mFilterCallbacks[mFilterId] = mFilterCallback;
+ mFilterCallback->updateFilterMQ(mFilterMQDescriptor);
+ // mDemuxCallback->updateGoldenOutputMap(goldenOutputFiles[i]);
+ status = mFilter->start();
+ if (status != Result::SUCCESS) {
+ return failure();
+ }
+ }
+
+ // Playback Input Module
+ PlaybackSettings playbackSetting = playbackConf.setting;
+ if (addPlaybackToDemux(playbackSetting) == failure() ||
+ getPlaybackMQDescriptor() == failure()) {
+ return failure();
+ }
+ for (int i = 0; i <= filterIdsSize; i++) {
+ if (mDvr->attachFilter(mFilters[mUsedFilterIds[i]]) != Result::SUCCESS) {
+ return failure();
+ }
+ }
+ mDvrCallback->startPlaybackInputThread(playbackConf, mPlaybackMQDescriptor);
+ status = mDvr->start();
+ if (status != Result::SUCCESS) {
+ return failure();
+ }
+
+ // Data Verify Module
+ std::map<uint32_t, sp<FilterCallback>>::iterator it;
+ for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
+ it->second->testFilterDataOutput();
+ }
+ mDvrCallback->stopPlaybackThread();
+
+ // Clean Up Module
+ for (int i = 0; i <= filterIdsSize; i++) {
+ if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
+ return failure();
+ }
+ }
+ if (mDvr->stop() != Result::SUCCESS) {
+ return failure();
+ }
+ mUsedFilterIds.clear();
+ mFilterCallbacks.clear();
+ mFilters.clear();
+ return closeDemux();
+}
+
+AssertionResult TunerHidlTest::recordDataFlowTest(vector<FilterConf> filterConf,
+ RecordSettings recordSetting,
+ vector<string> goldenOutputFiles) {
+ Result status;
+ hidl_vec<FrontendId> feIds;
+
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ feIds = frontendIds;
+ });
+
+ if (feIds.size() == 0) {
+ ALOGW("[ WARN ] Frontend isn't available");
+ return failure();
+ }
+
+ FrontendDvbtSettings dvbt{
+ .frequency = 1000,
+ };
+ FrontendSettings settings;
+ settings.dvbt(dvbt);
+
+ int filterIdsSize;
+ // Filter Configuration Module
+ for (int i = 0; i < filterConf.size(); i++) {
+ if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
+ failure() ||
+ // TODO use a map to save the FMQs/EvenFlags and pass to callback
+ getFilterMQDescriptor() == failure()) {
+ return failure();
+ }
+ filterIdsSize = mUsedFilterIds.size();
+ mUsedFilterIds.resize(filterIdsSize + 1);
+ mUsedFilterIds[filterIdsSize] = mFilterId;
+ mFilters[mFilterId] = mFilter;
+ }
+
+ // Record Config Module
+ if (addRecordToDemux(recordSetting) == failure() ||
+ getRecordMQDescriptor() == failure()) {
+ return failure();
+ }
+ for (int i = 0; i <= filterIdsSize; i++) {
+ if (mDvr->attachFilter(mFilters[mUsedFilterIds[i]]) != Result::SUCCESS) {
+ return failure();
+ }
+ }
+
+ mDvrCallback->startRecordOutputThread(recordSetting, mRecordMQDescriptor);
+ status = mDvr->start();
+ if (status != Result::SUCCESS) {
+ return failure();
+ }
+
+ if (setDemuxFrontendDataSource(feIds[0]) != success()) {
+ return failure();
+ }
+
+ // Data Verify Module
+ mDvrCallback->testRecordOutput();
+
+ // Clean Up Module
+ for (int i = 0; i <= filterIdsSize; i++) {
+ if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
+ return failure();
+ }
+ }
+ if (mFrontend->stopTune() != Result::SUCCESS) {
+ return failure();
+ }
+ mUsedFilterIds.clear();
+ mFilterCallbacks.clear();
+ mFilters.clear();
+ return closeDemux();
+}*/
+/*========================= End Data Flow Tests Implementation =========================*/
+
+/*=============================== Start Helper Functions ===============================*/
+FilterEventType TunerHidlTest::getFilterEventType(DemuxFilterType type) {
FilterEventType eventType = FilterEventType::UNDEFINED;
switch (type.mainType) {
case DemuxFilterMainType::TS:
@@ -998,358 +1263,151 @@
default:
break;
}
- mFilterCallback->setFilterEventType(eventType);
+ return eventType;
+}
+/*============================== End Helper Functions ==============================*/
+/***************************** End Test Implementation *****************************/
- // Configure the filter
- status = mFilter->configure(setting);
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
+/******************************** Start Test Entry **********************************/
+/*============================== Start Frontend Tests ==============================*/
+TEST_P(TunerHidlTest, getFrontendIds) {
+ description("Get Frontend ids and verify frontends exist");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
}
-::testing::AssertionResult TunerHidlTest::getFilterMQDescriptor() {
- Result status;
+TEST_P(TunerHidlTest, openFrontend) {
+ description("Open all the existing Frontends and close them");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
- if (!mDemux || !mFilter) {
- return ::testing::AssertionFailure();
- }
-
- mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
- mFilterMQDescriptor = filterMQDesc;
- status = result;
- });
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::playbackDataFlowTest(
- vector<FilterConf> filterConf, PlaybackConf playbackConf,
- vector<string> /*goldenOutputFiles*/) {
- Result status;
- int filterIdsSize;
- // Filter Configuration Module
- for (int i = 0; i < filterConf.size(); i++) {
- if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
- ::testing::AssertionFailure() ||
- // TODO use a map to save the FMQs/EvenFlags and pass to callback
- getFilterMQDescriptor() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
- filterIdsSize = mUsedFilterIds.size();
- mUsedFilterIds.resize(filterIdsSize + 1);
- mUsedFilterIds[filterIdsSize] = mFilterId;
- mFilters[mFilterId] = mFilter;
- mFilterCallbacks[mFilterId] = mFilterCallback;
- mFilterCallback->updateFilterMQ(mFilterMQDescriptor);
- // mDemuxCallback->updateGoldenOutputMap(goldenOutputFiles[i]);
- status = mFilter->start();
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- }
-
- // Playback Input Module
- PlaybackSettings playbackSetting = playbackConf.setting;
- if (addPlaybackToDemux(playbackSetting) == ::testing::AssertionFailure() ||
- getPlaybackMQDescriptor() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
- for (int i = 0; i <= filterIdsSize; i++) {
- if (mDvr->attachFilter(mFilters[mUsedFilterIds[i]]) != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- }
- mDvrCallback->startPlaybackInputThread(playbackConf, mPlaybackMQDescriptor);
- status = mDvr->start();
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
-
- // Data Verify Module
- std::map<uint32_t, sp<FilterCallback>>::iterator it;
- for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
- it->second->testFilterDataOutput();
- }
- mDvrCallback->stopPlaybackThread();
-
- // Clean Up Module
- for (int i = 0; i <= filterIdsSize; i++) {
- if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- }
- if (mDvr->stop() != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- mUsedFilterIds.clear();
- mFilterCallbacks.clear();
- mFilters.clear();
- return closeDemux();
-}
-
-::testing::AssertionResult TunerHidlTest::broadcastDataFlowTest(
- vector<FilterConf> filterConf, vector<string> /*goldenOutputFiles*/) {
- Result status;
- hidl_vec<FrontendId> feIds;
-
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- feIds = frontendIds;
- });
-
- if (feIds.size() == 0) {
- ALOGW("[ WARN ] Frontend isn't available");
- return ::testing::AssertionFailure();
- }
-
- FrontendDvbtSettings dvbt{
- .frequency = 1000,
- };
- FrontendSettings settings;
- settings.dvbt(dvbt);
-
- if (createDemuxWithFrontend(feIds[0], settings) != ::testing::AssertionSuccess()) {
- return ::testing::AssertionFailure();
- }
-
- int filterIdsSize;
- // Filter Configuration Module
- for (int i = 0; i < filterConf.size(); i++) {
- if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
- ::testing::AssertionFailure() ||
- // TODO use a map to save the FMQs/EvenFlags and pass to callback
- getFilterMQDescriptor() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
- filterIdsSize = mUsedFilterIds.size();
- mUsedFilterIds.resize(filterIdsSize + 1);
- mUsedFilterIds[filterIdsSize] = mFilterId;
- mFilters[mFilterId] = mFilter;
- mFilterCallbacks[mFilterId] = mFilterCallback;
- mFilterCallback->updateFilterMQ(mFilterMQDescriptor);
- status = mFilter->start();
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- }
-
- // Data Verify Module
- std::map<uint32_t, sp<FilterCallback>>::iterator it;
- for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
- it->second->testFilterDataOutput();
- }
-
- // Clean Up Module
- for (int i = 0; i <= filterIdsSize; i++) {
- if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- }
- if (mFrontend->stopTune() != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- mUsedFilterIds.clear();
- mFilterCallbacks.clear();
- mFilters.clear();
- return closeDemux();
-}
-
-::testing::AssertionResult TunerHidlTest::recordDataFlowTest(vector<FilterConf> filterConf,
- RecordSettings recordSetting,
- vector<string> /*goldenOutputFiles*/) {
- Result status;
- hidl_vec<FrontendId> feIds;
-
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- feIds = frontendIds;
- });
-
- if (feIds.size() == 0) {
- ALOGW("[ WARN ] Frontend isn't available");
- return ::testing::AssertionFailure();
- }
-
- FrontendDvbtSettings dvbt{
- .frequency = 1000,
- };
- FrontendSettings settings;
- settings.dvbt(dvbt);
-
- int filterIdsSize;
- // Filter Configuration Module
- for (int i = 0; i < filterConf.size(); i++) {
- if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
- ::testing::AssertionFailure() ||
- // TODO use a map to save the FMQs/EvenFlags and pass to callback
- getFilterMQDescriptor() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
- filterIdsSize = mUsedFilterIds.size();
- mUsedFilterIds.resize(filterIdsSize + 1);
- mUsedFilterIds[filterIdsSize] = mFilterId;
- mFilters[mFilterId] = mFilter;
- }
-
- // Record Config Module
- if (addRecordToDemux(recordSetting) == ::testing::AssertionFailure() ||
- getRecordMQDescriptor() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
- for (int i = 0; i <= filterIdsSize; i++) {
- if (mDvr->attachFilter(mFilters[mUsedFilterIds[i]]) != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- }
-
- mDvrCallback->startRecordOutputThread(recordSetting, mRecordMQDescriptor);
- status = mDvr->start();
- if (status != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
-
- if (createDemuxWithFrontend(feIds[0], settings) != ::testing::AssertionSuccess()) {
- return ::testing::AssertionFailure();
- }
-
- // Data Verify Module
- mDvrCallback->testRecordOutput();
-
- // Clean Up Module
- for (int i = 0; i <= filterIdsSize; i++) {
- if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- }
- if (mFrontend->stopTune() != Result::SUCCESS) {
- return ::testing::AssertionFailure();
- }
- mUsedFilterIds.clear();
- mFilterCallbacks.clear();
- mFilters.clear();
- return closeDemux();
-}
-
-/*
- * API STATUS TESTS
- */
-TEST_P(TunerHidlTest, CreateFrontend) {
- Result status;
- hidl_vec<FrontendId> feIds;
-
- description("Create Frontends");
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- feIds = frontendIds;
- });
-
- if (feIds.size() == 0) {
- ALOGW("[ WARN ] Frontend isn't available");
- return;
- }
-
- for (size_t i = 0; i < feIds.size(); i++) {
- ASSERT_TRUE(createFrontend(feIds[i]));
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(openFrontend(mFeIds[i]));
+ ASSERT_TRUE(closeFrontend());
}
}
TEST_P(TunerHidlTest, TuneFrontend) {
- Result status;
- hidl_vec<FrontendId> feIds;
-
- description("Tune Frontends and check callback onEvent");
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- feIds = frontendIds;
- });
-
- if (feIds.size() == 0) {
- ALOGW("[ WARN ] Frontend isn't available");
- return;
- }
-
- for (size_t i = 0; i < feIds.size(); i++) {
- ASSERT_TRUE(tuneFrontend(feIds[i]));
+ description("Tune one Frontend with specific setting and check Lock event");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
+ ALOGW("[vts] expected Frontend type is %d", frontendArray[0].type);
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ ALOGW("[vts] Frontend type is %d", mFrontendInfo.type);
+ if (mFrontendInfo.type != frontendArray[0].type) {
+ continue;
+ }
+ ASSERT_TRUE(openFrontend(mFeIds[i]));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(stopTuneFrontend());
+ ASSERT_TRUE(tuneFrontend(frontendArray[0]));
+ ASSERT_TRUE(stopTuneFrontend());
+ ASSERT_TRUE(closeFrontend());
+ break;
}
}
-TEST_P(TunerHidlTest, StopTuneFrontend) {
- Result status;
- hidl_vec<FrontendId> feIds;
+TEST_P(TunerHidlTest, AutoScanFrontend) {
+ description("Run an auto frontend scan with specific setting and check lock scanMessage");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
- description("stopTune Frontends");
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- feIds = frontendIds;
- });
-
- if (feIds.size() == 0) {
- ALOGW("[ WARN ] Frontend isn't available");
- return;
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ if (mFrontendInfo.type != frontendArray[0].type) {
+ continue;
+ }
+ ASSERT_TRUE(openFrontend(mFeIds[i]));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(stopScanFrontend());
+ ASSERT_TRUE(scanFrontend(frontendScanArray[0], FrontendScanType::SCAN_AUTO));
+ ASSERT_TRUE(stopScanFrontend());
+ ASSERT_TRUE(closeFrontend());
+ break;
}
+}
+/*=============================== End Frontend Tests ===============================*/
- for (size_t i = 0; i < feIds.size(); i++) {
- ASSERT_TRUE(stopTuneFrontend(feIds[i]));
+/*============================ Start Demux/Filter Tests ============================*/
+TEST_P(TunerHidlTest, OpenDemuxWithFrontendDataSource) {
+ description("Open Demux with a Frontend as its data source.");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
+
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ if (mFrontendInfo.type != frontendArray[0].type) {
+ continue;
+ }
+ ASSERT_TRUE(openFrontend(mFeIds[i]));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(openDemux());
+ ASSERT_TRUE(setDemuxFrontendDataSource(mFeIds[i]));
+ ASSERT_TRUE(closeDemux());
+ ASSERT_TRUE(closeFrontend());
+ break;
}
}
-TEST_P(TunerHidlTest, CloseFrontend) {
- Result status;
- hidl_vec<FrontendId> feIds;
+TEST_P(TunerHidlTest, OpenFilterInDemux) {
+ description("Open a filter in Demux.");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
- description("Close Frontends");
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- feIds = frontendIds;
- });
-
- if (feIds.size() == 0) {
- ALOGW("[ WARN ] Frontend isn't available");
- return;
- }
-
- for (size_t i = 0; i < feIds.size(); i++) {
- ASSERT_TRUE(closeFrontend(feIds[i]));
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ if (mFrontendInfo.type != frontendArray[0].type) {
+ continue;
+ }
+ ASSERT_TRUE(openFrontend(mFeIds[i]));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(openDemux());
+ ASSERT_TRUE(setDemuxFrontendDataSource(mFeIds[i]));
+ ASSERT_TRUE(openFilterInDemux(filterArray[0].type));
+ uint32_t filterId;
+ ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(closeFilter(filterId));
+ ASSERT_TRUE(closeDemux());
+ ASSERT_TRUE(closeFrontend());
+ break;
}
}
-TEST_P(TunerHidlTest, CreateDemuxWithFrontend) {
- Result status;
- hidl_vec<FrontendId> feIds;
+TEST_P(TunerHidlTest, StartFilterInDemux) {
+ description("Open and start a filter in Demux.");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
- description("Create Demux with Frontend");
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- feIds = frontendIds;
- });
-
- if (feIds.size() == 0) {
- ALOGW("[ WARN ] Frontend isn't available");
- return;
- }
-
- FrontendDvbtSettings dvbt{
- .frequency = 1000,
- };
- FrontendSettings settings;
- settings.dvbt(dvbt);
-
- for (size_t i = 0; i < feIds.size(); i++) {
- ASSERT_TRUE(createDemuxWithFrontend(feIds[i], settings));
- mFrontend->stopTune();
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ if (mFrontendInfo.type != frontendArray[0].type) {
+ continue;
+ }
+ ASSERT_TRUE(openFrontend(mFeIds[i]));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(openDemux());
+ ASSERT_TRUE(setDemuxFrontendDataSource(mFeIds[i]));
+ ASSERT_TRUE(openFilterInDemux(filterArray[0].type));
+ uint32_t filterId;
+ ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(configFilter(filterArray[0].setting, filterId));
+ ASSERT_TRUE(getFilterMQDescriptor(filterId));
+ ASSERT_TRUE(startFilter(filterId));
+ ASSERT_TRUE(stopFilter(filterId));
+ ASSERT_TRUE(closeFilter(filterId));
+ ASSERT_TRUE(closeDemux());
+ ASSERT_TRUE(closeFrontend());
+ break;
}
}
+/*============================ End Demux/Filter Tests ============================*/
-TEST_P(TunerHidlTest, CreateDemux) {
- description("Create Demux");
- ASSERT_TRUE(createDemux());
-}
-
-TEST_P(TunerHidlTest, CloseDemux) {
- description("Close Demux");
- ASSERT_TRUE(closeDemux());
-}
-
-TEST_P(TunerHidlTest, CreateDescrambler) {
+/*============================ Start Descrambler Tests ============================*/
+/*
+ * TODO: re-enable the tests after finalizing the test refactoring.
+ */
+/*TEST_P(TunerHidlTest, CreateDescrambler) {
description("Create Descrambler");
ASSERT_TRUE(createDescrambler());
}
@@ -1357,11 +1415,44 @@
TEST_P(TunerHidlTest, CloseDescrambler) {
description("Close Descrambler");
ASSERT_TRUE(closeDescrambler());
+}*/
+/*============================== End Descrambler Tests ==============================*/
+
+/*============================== Start Data Flow Tests ==============================*/
+TEST_P(TunerHidlTest, BroadcastDataFlowWithAudioFilterTest) {
+ description("Open Demux with a Frontend as its data source.");
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
+
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ if (mFrontendInfo.type != frontendArray[0].type) {
+ continue;
+ }
+ ASSERT_TRUE(openFrontend(mFeIds[i]));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(openDemux());
+ ASSERT_TRUE(setDemuxFrontendDataSource(mFeIds[i]));
+ ASSERT_TRUE(openFilterInDemux(filterArray[0].type));
+ uint32_t filterId;
+ ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(configFilter(filterArray[0].setting, filterId));
+ ASSERT_TRUE(getFilterMQDescriptor(filterId));
+ ASSERT_TRUE(startFilter(filterId));
+ // tune test
+ ASSERT_TRUE(tuneFrontend(frontendArray[0]));
+ // broadcast data flow test
+ ASSERT_TRUE(broadcastDataFlowTest(goldenOutputFiles));
+ ASSERT_TRUE(stopTuneFrontend());
+ ASSERT_TRUE(stopFilter(filterId));
+ ASSERT_TRUE(closeFilter(filterId));
+ ASSERT_TRUE(closeDemux());
+ ASSERT_TRUE(closeFrontend());
+ break;
+ }
}
/*
- * DATA FLOW TESTS
- *
* TODO: re-enable the tests after finalizing the testing stream.
*/
/*TEST_P(TunerHidlTest, PlaybackDataFlowWithSectionFilterTest) {
@@ -1407,36 +1498,6 @@
ASSERT_TRUE(playbackDataFlowTest(filterConf, playbackConf, goldenOutputFiles));
}
-TEST_P(TunerHidlTest, BroadcastDataFlowWithPesFilterTest) {
- description("Feed ts data from frontend and test with PES filter");
-
- // todo modulize the filter conf parser
- vector<FilterConf> filterConf;
- filterConf.resize(1);
-
- DemuxFilterSettings filterSetting;
- DemuxTsFilterSettings tsFilterSetting{
- .tpid = 119,
- };
- DemuxFilterPesDataSettings pesFilterSetting;
- tsFilterSetting.filterSettings.pesData(pesFilterSetting);
- filterSetting.ts(tsFilterSetting);
-
- DemuxFilterType type{
- .mainType = DemuxFilterMainType::TS,
- };
- type.subType.tsFilterType(DemuxTsFilterType::PES);
- FilterConf pesFilterConf{
- .type = type,
- .setting = filterSetting,
- };
- filterConf[0] = pesFilterConf;
-
- vector<string> goldenOutputFiles;
-
- ASSERT_TRUE(broadcastDataFlowTest(filterConf, goldenOutputFiles));
-}
-
TEST_P(TunerHidlTest, RecordDataFlowWithTsRecordFilterTest) {
description("Feed ts data from frontend to recording and test with ts record filter");
@@ -1474,7 +1535,8 @@
ASSERT_TRUE(recordDataFlowTest(filterConf, recordSetting, goldenOutputFiles));
}*/
-
+/*============================== End Data Flow Tests ==============================*/
+/******************************** End Test Entry **********************************/
} // namespace
INSTANTIATE_TEST_SUITE_P(
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
new file mode 100644
index 0000000..55ca857
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/IDvr.h>
+#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
+#include <android/hardware/tv/tuner/1.0/IFilter.h>
+#include <android/hardware/tv/tuner/1.0/IFilterCallback.h>
+#include <android/hardware/tv/tuner/1.0/IFrontend.h>
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+
+using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
+using android::hardware::tv::tuner::V1_0::DemuxTpid;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
+using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::FrontendType;
+
+namespace {
+
+#define frontend_transponders_count 1
+#define channels_count 1
+#define frontend_scan_count 1
+#define filter_count 2
+
+struct FilterConfig {
+ DemuxFilterType type;
+ DemuxFilterSettings setting;
+};
+
+struct FrontendConfig {
+ FrontendType type;
+ FrontendSettings settings;
+};
+
+struct ChannelConfig {
+ int32_t frontendId;
+ int32_t channelId;
+ std::string channelName;
+ DemuxTpid videoPid;
+ DemuxTpid audioPid;
+};
+
+static FrontendConfig frontendArray[frontend_transponders_count];
+static FrontendConfig frontendScanArray[channels_count];
+static ChannelConfig channelArray[frontend_scan_count];
+static FilterConfig filterArray[filter_count];
+static vector<string> goldenOutputFiles;
+
+/** Configuration array for the frontend tune test */
+inline void initFrontendConfig() {
+ FrontendDvbtSettings dvbtSettings{
+ .frequency = 578000,
+ .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
+ .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
+ .constellation = FrontendDvbtConstellation::AUTO,
+ .hierarchy = FrontendDvbtHierarchy::AUTO,
+ .hpCoderate = FrontendDvbtCoderate::AUTO,
+ .lpCoderate = FrontendDvbtCoderate::AUTO,
+ .guardInterval = FrontendDvbtGuardInterval::AUTO,
+ .isHighPriority = true,
+ .standard = FrontendDvbtStandard::T,
+ };
+ frontendArray[0].type = FrontendType::DVBT, frontendArray[0].settings.dvbt(dvbtSettings);
+};
+
+/** Configuration array for the frontend scan test */
+inline void initFrontendScanConfig() {
+ frontendScanArray[0].type = FrontendType::DVBT, frontendScanArray[0].settings.dvbt({
+ .frequency = 577000,
+ });
+};
+
+/** Configuration array for the filter test */
+inline void initFilterConfig() {
+ // TS Video filter setting
+ filterArray[0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+ filterArray[0].setting.ts().tpid = 49;
+ filterArray[0].setting.ts().filterSettings.av({.isPassthrough = false});
+ // TS PES filter setting
+ filterArray[1].type.mainType = DemuxFilterMainType::TS;
+ filterArray[1].type.subType.tsFilterType(DemuxTsFilterType::PES);
+ filterArray[1].setting.ts().tpid = 256;
+ filterArray[1].setting.ts().filterSettings.pesData({
+ .isRaw = true,
+ .streamId = 0xbd,
+ });
+};
+
+} // namespace
\ No newline at end of file
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
index 84556b5..406a899 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
@@ -23,6 +23,9 @@
/* Period of silence preceding primitive. */
int delayMs;
CompositePrimitive primitive;
- /* 0.0 (exclusive) - 1.0 (inclusive) */
+ /*
+ * 0.0 (inclusive) - 1.0 (inclusive),
+ * where 0.0 is minimum "feelable" amplitude.
+ */
float scale;
}
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
index 0fdfa5d..8e82db0 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
@@ -21,37 +21,53 @@
enum CompositePrimitive {
/**
* No haptic effect. Used to generate extended delays between primitives.
+ *
+ * Support is required.
*/
NOOP,
/**
* This effect should produce a sharp, crisp click sensation.
+ *
+ * Support is required.
*/
CLICK,
/**
* A haptic effect that simulates downwards movement with gravity. Often
* followed by extra energy of hitting and reverberation to augment
* physicality.
+ *
+ * Support is optional.
*/
THUD,
/**
* A haptic effect that simulates spinning momentum.
+ *
+ * Support is optional.
*/
SPIN,
/**
* A haptic effect that simulates quick upward movement against gravity.
+ *
+ * Support is required.
*/
QUICK_RISE,
/**
* A haptic effect that simulates slow upward movement against gravity.
+ *
+ * Support is required.
*/
SLOW_RISE,
/**
* A haptic effect that simulates quick downwards movement with gravity.
+ *
+ * Support is required.
*/
QUICK_FALL,
/**
* This very short effect should produce a light crisp sensation intended
* to be used repetitively for dynamic feedback.
+ *
+ * Support is required.
*/
LIGHT_TICK,
}
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index 06a8bf5..0b21248 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -161,8 +161,8 @@
* List of supported effect primitive.
*
* Return the effect primitives which are supported by the compose API.
- * Implementations are expected to support all primitives of the interface
- * version that they implement.
+ * Implementations are expected to support all required primitives of the
+ * interface version that they implement (see primitive definitions).
*/
CompositePrimitive[] getSupportedPrimitives();
@@ -202,6 +202,12 @@
* once enabled and assigned an effect to play. This may not be supported
* and this support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL).
*
+ * The always-on source ID is conveyed directly to clients through
+ * device/board configuration files ensuring that no ID is assigned to
+ * multiple clients. No client should use this API unless explicitly
+ * assigned an always-on source ID. Clients must develop their own way to
+ * get IDs from vendor in a stable way.
+ *
* @param id The device-specific always-on source ID to enable.
* @param effect The type of haptic event to trigger.
* @param strength The intensity of haptic event to trigger.
@@ -212,6 +218,12 @@
* Disable an always-on haptic source. This may not be supported and this
* support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL).
*
+ * The always-on source ID is conveyed directly to clients through
+ * device/board configuration files ensuring that no ID is assigned to
+ * multiple clients. No client should use this API unless explicitly
+ * assigned an always-on source ID. Clients must develop their own way to
+ * get IDs from vendor in a stable way.
+ *
* @param id The device-specific always-on source ID to disable.
*/
void alwaysOnDisable(in int id);
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 9236b95..b359100 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -146,7 +146,7 @@
if (e.delayMs > kComposeDelayMaxMs) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- if (e.scale <= 0.0f || e.scale > 1.0f) {
+ if (e.scale < 0.0f || e.scale > 1.0f) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
if (std::find(supported.begin(), supported.end(), e.primitive) == supported.end()) {
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 411fe7a..8340517 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -21,6 +21,7 @@
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
+#include <cmath>
#include <future>
using android::ProcessState;
@@ -53,6 +54,11 @@
android::enum_range<CompositePrimitive>().begin(),
android::enum_range<CompositePrimitive>().end()};
+const std::vector<CompositePrimitive> kOptionalPrimitives = {
+ CompositePrimitive::THUD,
+ CompositePrimitive::SPIN,
+};
+
const std::vector<CompositePrimitive> kInvalidPrimitives = {
static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.front()) - 1),
static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
@@ -128,7 +134,6 @@
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
<< toString(effect) << " " << toString(strength);
- EXPECT_EQ(lengthMs, 0);
}
}
}
@@ -157,7 +162,6 @@
EXPECT_GT(lengthMs, 0);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
- EXPECT_EQ(lengthMs, 0);
}
if (!status.isOk()) continue;
@@ -177,7 +181,6 @@
int lengthMs;
Status status = vibrator->perform(effect, strength, callback, &lengthMs);
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
- EXPECT_EQ(lengthMs, 0);
}
}
}
@@ -267,38 +270,56 @@
EXPECT_EQ(Status::EX_NONE, vibrator->getSupportedPrimitives(&supported).exceptionCode());
- std::sort(supported.begin(), supported.end());
+ for (auto primitive : kCompositePrimitives) {
+ bool isPrimitiveSupported =
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ bool isPrimitiveOptional =
+ std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
+ kOptionalPrimitives.end();
- EXPECT_EQ(kCompositePrimitives, supported);
+ EXPECT_TRUE(isPrimitiveSupported || isPrimitiveOptional) << toString(primitive);
+ }
}
}
TEST_P(VibratorAidl, GetPrimitiveDuration) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
- int32_t duration;
+ std::vector<CompositePrimitive> supported;
+ ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
for (auto primitive : kCompositePrimitives) {
- EXPECT_EQ(Status::EX_NONE,
- vibrator->getPrimitiveDuration(primitive, &duration).exceptionCode());
+ bool isPrimitiveSupported =
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ int32_t duration;
+
+ Status status = vibrator->getPrimitiveDuration(primitive, &duration);
+
+ if (isPrimitiveSupported) {
+ EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
+ } else {
+ EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+ }
}
}
}
TEST_P(VibratorAidl, ComposeValidPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+ std::vector<CompositePrimitive> supported;
int32_t maxDelay, maxSize;
+ ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
std::vector<CompositeEffect> composite;
- for (auto primitive : kCompositePrimitives) {
+ for (auto primitive : supported) {
CompositeEffect effect;
effect.delayMs = std::rand() % (maxDelay + 1);
effect.primitive = primitive;
- effect.scale = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
+ effect.scale = static_cast<float>(std::rand()) / RAND_MAX;
composite.emplace_back(effect);
if (composite.size() == maxSize) {
@@ -317,7 +338,21 @@
TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
- for (auto primitive : kInvalidPrimitives) {
+ auto unsupported = kInvalidPrimitives;
+ std::vector<CompositePrimitive> supported;
+
+ ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+
+ for (auto primitive : kCompositePrimitives) {
+ bool isPrimitiveSupported =
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
+
+ if (!isPrimitiveSupported) {
+ unsupported.push_back(primitive);
+ }
+ }
+
+ for (auto primitive : unsupported) {
std::vector<CompositeEffect> composite(1);
for (auto& effect : composite) {
@@ -332,7 +367,33 @@
}
}
-TEST_P(VibratorAidl, CompseDelayBoundary) {
+TEST_P(VibratorAidl, ComposeScaleBoundary) {
+ if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+ std::vector<CompositeEffect> composite(1);
+ CompositeEffect& effect = composite[0];
+
+ effect.delayMs = 0;
+ effect.primitive = CompositePrimitive::CLICK;
+
+ effect.scale = std::nextafter(0.0f, -1.0f);
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->compose(composite, nullptr).exceptionCode());
+
+ effect.scale = 0.0f;
+ EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+
+ effect.scale = 1.0f;
+ EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+
+ effect.scale = std::nextafter(1.0f, 2.0f);
+ EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+ vibrator->compose(composite, nullptr).exceptionCode());
+
+ vibrator->off();
+ }
+}
+
+TEST_P(VibratorAidl, ComposeDelayBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
int32_t maxDelay;
@@ -357,7 +418,7 @@
}
}
-TEST_P(VibratorAidl, CompseSizeBoundary) {
+TEST_P(VibratorAidl, ComposeSizeBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
int32_t maxSize;
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
index 7ea5462..dbf2b91 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
@@ -21,6 +21,8 @@
#include "supplicant_hidl_test_utils_1_3.h"
using ::android::sp;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
using ::android::hardware::wifi::supplicant::V1_3::ISupplicant;
using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface;
using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
@@ -43,3 +45,15 @@
return ISupplicant::castFrom(
getSupplicant(supplicant_instance_name, isP2pOn));
}
+
+bool isFilsSupported(sp<ISupplicantStaIface> sta_iface) {
+ uint32_t keyMgmtMask = 0;
+ sta_iface->getKeyMgmtCapabilities_1_3(
+ [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ keyMgmtMask = keyMgmtMaskInternal;
+ });
+
+ return (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
+ ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384));
+}
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
index f8dca13..69fc598 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
@@ -31,4 +31,7 @@
supplicant);
android::sp<android::hardware::wifi::supplicant::V1_3::ISupplicant>
getSupplicant_1_3(const std::string& supplicant_instance_name, bool isP2pOn);
+bool isFilsSupported(
+ android::sp<android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface>
+ sta_iface);
#endif /* SUPPLICANT_HIDL_TEST_UTILS_1_3_H */
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
index f7019d2..3754520 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -517,7 +517,10 @@
* FilsHlpAddRequest
*/
TEST_P(SupplicantStaIfaceHidlTest, FilsHlpAddRequest) {
- uint32_t keyMgmtMask = 0;
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
uint8_t destMacAddr[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
std::vector<uint8_t> pktBuffer = {
0x08, 0x00, 0x45, 0x10, 0x01, 0x3a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
@@ -548,22 +551,9 @@
0x63, 0x70, 0x2d, 0x52, 0x37, 0x0a, 0x01, 0x03, 0x06, 0x0f, 0x1a, 0x1c,
0x33, 0x3a, 0x3b, 0x2b, 0xff, 0x00};
- sta_iface_->getKeyMgmtCapabilities_1_3(
- [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
- EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
- keyMgmtMask = keyMgmtMaskInternal;
- });
-
- SupplicantStatusCode expectedStatusCode =
- (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
- ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
- ? SupplicantStatusCode::SUCCESS
- : SupplicantStatusCode::FAILURE_UNKNOWN;
-
sta_iface_->filsHlpAddRequest(
- destMacAddr, pktBuffer,
- [expectedStatusCode](const SupplicantStatus& status) {
- EXPECT_EQ(expectedStatusCode, status.code);
+ destMacAddr, pktBuffer, [](const SupplicantStatus& status) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
});
}
@@ -571,23 +561,14 @@
* FilsHlpFlushRequest
*/
TEST_P(SupplicantStaIfaceHidlTest, FilsHlpFlushRequest) {
- uint32_t keyMgmtMask = 0;
- sta_iface_->getKeyMgmtCapabilities_1_3(
- [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
- EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
- keyMgmtMask = keyMgmtMaskInternal;
- });
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
- SupplicantStatusCode expectedStatusCode =
- (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
- ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
- ? SupplicantStatusCode::SUCCESS
- : SupplicantStatusCode::FAILURE_UNKNOWN;
-
- sta_iface_->filsHlpFlushRequest(
- [expectedStatusCode](const SupplicantStatus& status) {
- EXPECT_EQ(expectedStatusCode, status.code);
- });
+ sta_iface_->filsHlpFlushRequest([](const SupplicantStatus& status) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ });
}
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaIfaceHidlTest,
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 6be24bc..9c40de1 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -290,23 +290,14 @@
* SetEapErp
*/
TEST_P(SupplicantStaNetworkHidlTest, SetEapErp) {
- uint32_t keyMgmtMask = 0;
- sta_iface_->getKeyMgmtCapabilities_1_3(
- [&](const SupplicantStatus &status, uint32_t keyMgmtMaskInternal) {
- EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
- keyMgmtMask = keyMgmtMaskInternal;
- });
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
- SupplicantStatusCode expectedStatusCode =
- (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
- ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
- ? SupplicantStatusCode::SUCCESS
- : SupplicantStatusCode::FAILURE_UNKNOWN;
-
- sta_network_->setEapErp(
- true, [expectedStatusCode](const SupplicantStatus &status) {
- EXPECT_EQ(expectedStatusCode, status.code);
- });
+ sta_network_->setEapErp(true, [](const SupplicantStatus &status) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ });
}
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaNetworkHidlTest,