Merge "Duplicate setting when generate fake data" into rvc-dev
diff --git a/Android.bp b/Android.bp
index f64968f..9e1df13 100644
--- a/Android.bp
+++ b/Android.bp
@@ -21,7 +21,7 @@
// Lists all dependencies that can *not* be expected on the device.
static_libs: [
- "VtsHalHidlTargetTestBase",
+ "VtsHalHidlTestUtils",
"libhidl-gen-utils",
],
@@ -47,3 +47,15 @@
require_root: true,
}
+
+// TODO: Remove this after all vts tests under vendor/qcom are converted to
+// parameterized gtest.
+cc_defaults {
+ name: "Vts10HalTargetTestDefaults",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ ],
+ static_libs: [
+ "VtsHalHidlTargetTestBase",
+ ],
+}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 543acf6..acae4f3 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -8,6 +8,9 @@
},
{
"name": "hal_implementation_test"
+ },
+ {
+ "name": "VtsHalTvInputV1_0TargetTest"
}
]
}
diff --git a/atrace/1.0/vts/functional/Android.bp b/atrace/1.0/vts/functional/Android.bp
index ae24968..07d3f7f 100644
--- a/atrace/1.0/vts/functional/Android.bp
+++ b/atrace/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalAtraceV1_0TargetTest.cpp"],
static_libs: ["android.hardware.atrace@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/audio/2.0/config/Android.bp b/audio/2.0/config/Android.bp
new file mode 100644
index 0000000..65a32eb
--- /dev/null
+++ b/audio/2.0/config/Android.bp
@@ -0,0 +1,20 @@
+//
+// 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.
+//
+
+filegroup {
+ name: "audio_policy_configuration_V2_0",
+ srcs: ["audio_policy_configuration.xsd"],
+}
diff --git a/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h b/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h
deleted file mode 100644
index 2b240ce..0000000
--- a/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ENVIRONMENT_TEARDOWN_H
-#define ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ENVIRONMENT_TEARDOWN_H
-
-#include <functional>
-#include <list>
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace common {
-namespace test {
-namespace utility {
-
-/** Register callback for static object destruction
- * Avoid destroying static objects after main return.
- * Post main return destruction leads to incorrect gtest timing measurements as
- * well as harder debuging if anything goes wrong during destruction. */
-class EnvironmentTearDown {
- public:
- using TearDownFunc = std::function<void()>;
- void registerTearDown(TearDownFunc&& tearDown) { tearDowns.push_front(std::move(tearDown)); }
-
- protected:
- void executeAllTearDowns() {
- // Call the tear downs in reverse order of insertion
- for (auto& tearDown : tearDowns) {
- tearDown();
- }
- }
-
- private:
- std::list<TearDownFunc> tearDowns;
-};
-
-} // namespace utility
-} // namespace test
-} // namespace common
-} // namespace audio
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ENVIRONMENT_TEARDOWN_H
diff --git a/audio/common/all-versions/test/utility/include/utility/ValidateXml.h b/audio/common/all-versions/test/utility/include/utility/ValidateXml.h
index ee206f7..274a10b 100644
--- a/audio/common/all-versions/test/utility/include/utility/ValidateXml.h
+++ b/audio/common/all-versions/test/utility/include/utility/ValidateXml.h
@@ -51,8 +51,31 @@
*/
template <bool atLeastOneRequired = true>
::testing::AssertionResult validateXmlMultipleLocations(
- const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr,
- const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath);
+ const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr,
+ const char* xmlFileName, const std::vector<std::string>& xmlFileLocations,
+ const char* xsdFilePath);
+template <bool atLeastOneRequired = true>
+::testing::AssertionResult validateXmlMultipleLocations(
+ const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr,
+ const char* xmlFileName, std::initializer_list<const char*> xmlFileLocations,
+ const char* xsdFilePath) {
+ return validateXmlMultipleLocations<atLeastOneRequired>(
+ xmlFileNameExpr, xmlFileLocationsExpr, xsdFilePathExpr, xmlFileName,
+ std::vector<std::string>(xmlFileLocations.begin(), xmlFileLocations.end()),
+ xsdFilePath);
+}
+template <bool atLeastOneRequired = true>
+::testing::AssertionResult validateXmlMultipleLocations(const char* xmlFileNameExpr,
+ const char* xmlFileLocationsExpr,
+ const char* xsdFilePathExpr,
+ const char* xmlFileName,
+ std::vector<const char*> xmlFileLocations,
+ const char* xsdFilePath) {
+ return validateXmlMultipleLocations<atLeastOneRequired>(
+ xmlFileNameExpr, xmlFileLocationsExpr, xsdFilePathExpr, xmlFileName,
+ std::vector<std::string>(xmlFileLocations.begin(), xmlFileLocations.end()),
+ xsdFilePath);
+}
/** ASSERT that all found XML are valid according to an xsd. */
#define ASSERT_VALID_XML_MULTIPLE_LOCATIONS(xmlFileName, xmlFileLocations, xsdFilePath) \
diff --git a/audio/common/all-versions/test/utility/src/ValidateXml.cpp b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
index bdafa82..a866104 100644
--- a/audio/common/all-versions/test/utility/src/ValidateXml.cpp
+++ b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
@@ -131,14 +131,15 @@
template <bool atLeastOneRequired>
::testing::AssertionResult validateXmlMultipleLocations(
- const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr,
- const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath) {
+ const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr,
+ const char* xmlFileName, const std::vector<std::string>& xmlFileLocations,
+ const char* xsdFilePath) {
using namespace std::string_literals;
std::vector<std::string> errors;
std::vector<std::string> foundFiles;
- for (const char* location : xmlFileLocations) {
+ for (const auto& location : xmlFileLocations) {
std::string xmlFilePath = location + "/"s + xmlFileName;
if (access(xmlFilePath.c_str(), F_OK) != 0) {
// If the file does not exist ignore this location and fallback on the next one
@@ -166,14 +167,12 @@
: "\nWhere no file might exist.");
}
-template ::testing::AssertionResult validateXmlMultipleLocations<true>(const char*, const char*,
- const char*, const char*,
- std::vector<const char*>,
- const char*);
-template ::testing::AssertionResult validateXmlMultipleLocations<false>(const char*, const char*,
- const char*, const char*,
- std::vector<const char*>,
- const char*);
+template ::testing::AssertionResult validateXmlMultipleLocations<true>(
+ const char*, const char*, const char*, const char*, const std::vector<std::string>&,
+ const char*);
+template ::testing::AssertionResult validateXmlMultipleLocations<false>(
+ const char*, const char*, const char*, const char*, const std::vector<std::string>&,
+ const char*);
} // namespace utility
} // namespace test
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index b8b7fee..0af81b2 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -18,8 +18,11 @@
export_include_dirs: ["include"],
- shared_libs: [
+ static_libs: [
"libaudiofoundation",
+ ],
+
+ shared_libs: [
"libbase",
"libcutils",
"libfmq",
@@ -52,7 +55,7 @@
"-DMAJOR_VERSION=2",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -68,7 +71,7 @@
"-DMAJOR_VERSION=4",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -83,7 +86,7 @@
"-DMAJOR_VERSION=5",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
cc_library_shared {
@@ -98,5 +101,5 @@
"-DMAJOR_VERSION=6",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
- ]
+ ],
}
diff --git a/audio/core/all-versions/vts/functional/2.0/EnvironmentTearDown.h b/audio/core/all-versions/vts/functional/2.0/EnvironmentTearDown.h
deleted file mode 100644
index 6373e39..0000000
--- a/audio/core/all-versions/vts/functional/2.0/EnvironmentTearDown.h
+++ /dev/null
@@ -1,34 +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.
- */
-
-#ifndef ANDROID_HARDWARE_AUDIO_CORE_2_0_ENVIRONMENT_TEARDOWN_H
-#define ANDROID_HARDWARE_AUDIO_CORE_2_0_ENVIRONMENT_TEARDOWN_H
-
-#include <VtsHalHidlTargetTestEnvBase.h>
-#include <gtest/gtest.h>
-
-#include "utility/EnvironmentTearDown.h"
-
-class Environment : public ::android::hardware::audio::common::test::utility::EnvironmentTearDown,
- public ::testing::VtsHalHidlTargetTestEnvBase {
- private:
- void HidlTearDown() override {
- executeAllTearDowns();
- VtsHalHidlTargetTestEnvBase::HidlTearDown();
- }
-};
-
-#endif // ANDROID_HARDWARE_AUDIO_CORE_2_0_ENVIRONMENT_TEARDOWN_H
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index b40a329..e09eeab 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -17,54 +17,6 @@
// pull in all the <= 5.0 tests
#include "5.0/AudioPrimaryHidlHalTest.cpp"
-const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
- static std::vector<DeviceParameter> parameters = [] {
- std::vector<DeviceParameter> result;
- const auto factories =
- ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
- for (const auto& factoryName : factories) {
- result.emplace_back(factoryName,
- DeviceManager::getInstance().getPrimary(factoryName) != nullptr
- ? DeviceManager::kPrimaryDevice
- : "");
- }
- return result;
- }();
- return parameters;
-}
-
-const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests() {
- static std::vector<DeviceParameter> parameters = [] {
- std::vector<DeviceParameter> result;
- const auto primary = std::find_if(
- getDeviceParameters().begin(), getDeviceParameters().end(), [](const auto& elem) {
- return std::get<PARAM_DEVICE_NAME>(elem) == DeviceManager::kPrimaryDevice;
- });
- if (primary != getDeviceParameters().end()) result.push_back(*primary);
- return result;
- }();
- return parameters;
-}
-
-const std::vector<DeviceParameter>& getDeviceParameters() {
- static std::vector<DeviceParameter> parameters = [] {
- std::vector<DeviceParameter> result;
- const auto factories =
- ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
- const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames();
- result.reserve(devices.size());
- for (const auto& factoryName : factories) {
- for (const auto& deviceName : devices) {
- if (DeviceManager::getInstance().get(factoryName, deviceName) != nullptr) {
- result.emplace_back(factoryName, deviceName);
- }
- }
- }
- return result;
- }();
- return parameters;
-}
-
const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
static std::vector<DeviceConfigParameter> parameters = [] {
std::vector<DeviceConfigParameter> result;
diff --git a/audio/core/all-versions/vts/functional/6.0/EnvironmentTearDown.h b/audio/core/all-versions/vts/functional/6.0/EnvironmentTearDown.h
deleted file mode 100644
index 593759f..0000000
--- a/audio/core/all-versions/vts/functional/6.0/EnvironmentTearDown.h
+++ /dev/null
@@ -1,35 +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.
- */
-
-#ifndef ANDROID_HARDWARE_AUDIO_CORE_6_0_ENVIRONMENT_TEARDOWN_H
-#define ANDROID_HARDWARE_AUDIO_CORE_6_0_ENVIRONMENT_TEARDOWN_H
-
-#include <gtest/gtest.h>
-
-#include "utility/EnvironmentTearDown.h"
-
-class Environment : public ::android::hardware::audio::common::test::utility::EnvironmentTearDown,
- public ::testing::Environment {
- public:
- void init(int* /*argc*/, char** /*argv*/) {} // emulate VtsHalHidlTargetTestEnvBase
- private:
- void TearDown() override { executeAllTearDowns(); }
-};
-
-// FIXME: Will be removed while making getDeviceParameters to use the config
-static constexpr const char* kDefaultServiceName = "default";
-
-#endif // ANDROID_HARDWARE_AUDIO_CORE_6_0_ENVIRONMENT_TEARDOWN_H
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 715f376..729ee7a 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -31,7 +31,10 @@
header_libs: [
"android.hardware.audio.common.util@all-versions",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
cc_test {
@@ -49,6 +52,12 @@
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
],
+ data: [
+ ":audio_policy_configuration_V2_0",
+ ],
+ // Use test_config for vts-core suite.
+ // TODO(b/146104851): Add auto-gen rules and remove it.
+ test_config: "VtsHalAudioV2_0TargetTest.xml",
}
cc_test {
@@ -66,6 +75,12 @@
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
],
+ data: [
+ ":audio_policy_configuration_V4_0",
+ ],
+ // Use test_config for vts-core suite.
+ // TODO(b/146104851): Add auto-gen rules and remove it.
+ test_config: "VtsHalAudioV4_0TargetTest.xml",
}
cc_test {
@@ -83,6 +98,12 @@
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
],
+ data: [
+ ":audio_policy_configuration_V5_0",
+ ],
+ // Use test_config for vts-core suite.
+ // TODO(b/146104851): Add auto-gen rules and remove it.
+ test_config: "VtsHalAudioV5_0TargetTest.xml",
}
cc_test {
@@ -100,14 +121,10 @@
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
],
- // Use test_config for vts-core suite.
- // TODO(b/146104851): Add auto-gen rules and remove it.
- test_config: "VtsHalAudioV6_0TargetTest.xml",
data: [
":audio_policy_configuration_V6_0",
],
- test_suites: [
- "general-tests",
- "vts-core",
- ],
+ // Use test_config for vts-core suite.
+ // TODO(b/146104851): Add auto-gen rules and remove it.
+ test_config: "VtsHalAudioV6_0TargetTest.xml",
}
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index b77aec9..d5af335 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -34,11 +34,8 @@
#include <hwbinder/IPCThreadState.h>
-#if MAJOR_VERSION <= 5
-#include <VtsHalHidlTargetTestBase.h>
-#endif
-
#include <android-base/logging.h>
+#include <system/audio_config.h>
#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
@@ -49,10 +46,8 @@
#include <Serializer.h>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
-#if MAJOR_VERSION >= 6
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
-#endif
#include <common/all-versions/VersionUtils.h>
@@ -61,12 +56,6 @@
#include "utility/ReturnIn.h"
#include "utility/ValidateXml.h"
-#if MAJOR_VERSION <= 5
-#include "2.0/EnvironmentTearDown.h"
-#elif MAJOR_VERSION >= 6
-#include "6.0/EnvironmentTearDown.h"
-#endif
-
/** Provide version specific functions that are used in the generic tests */
#if MAJOR_VERSION == 2
#include "2.0/AudioPrimaryHidlHalUtils.h"
@@ -114,30 +103,10 @@
static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////// Environment /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-class AudioHidlTestEnvironment : public ::Environment {
- public:
-#if MAJOR_VERSION <= 5
- void registerTestServices() override { registerTestService<IDevicesFactory>(); }
-#endif
-};
-
-// Instance to register global tearDown
-static AudioHidlTestEnvironment* environment;
-
#define AUDIO_PRIMARY_HIDL_HAL_TEST
#include "DeviceManager.h"
-#if MAJOR_VERSION <= 5
-using HidlTestBase = ::testing::VtsHalHidlTargetTestBase;
-#elif MAJOR_VERSION >= 6
-using HidlTestBase = ::testing::Test;
-#endif
-
-class HidlTest : public HidlTestBase {
+class HidlTest : public ::testing::Test {
public:
virtual ~HidlTest() = default;
// public access to avoid annoyances when using this method in template classes
@@ -167,22 +136,12 @@
////////////////////////// Audio policy configuration ////////////////////////
//////////////////////////////////////////////////////////////////////////////
-static const std::vector<const char*> kConfigLocations = {"/odm/etc", "/vendor/etc", "/system/etc"};
static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
// Stringify the argument.
#define QUOTE(x) #x
#define STRINGIFY(x) QUOTE(x)
-TEST(CheckConfig, audioPolicyConfigurationValidation) {
- RecordProperty("description",
- "Verify that the audio policy configuration file "
- "is valid according to the schema");
-
- const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
- EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName, kConfigLocations, xsd);
-}
-
struct PolicyConfigData {
android::HwModuleCollection hwModules;
android::DeviceVector availableOutputDevices;
@@ -195,8 +154,8 @@
PolicyConfig()
: AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
defaultOutputDevice) {
- for (const char* location : kConfigLocations) {
- std::string path = std::string(location) + '/' + kConfigFileName;
+ for (const auto& location : android::audio_get_configuration_paths()) {
+ std::string path = location + '/' + kConfigFileName;
if (access(path.c_str(), F_OK) == 0) {
mFilePath = path;
break;
@@ -229,7 +188,7 @@
std::string getError() const {
if (mFilePath.empty()) {
return std::string{"Could not find "} + kConfigFileName +
- " file in: " + testing::PrintToString(kConfigLocations);
+ " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
} else {
return "Invalid config file: " + mFilePath;
}
@@ -254,32 +213,11 @@
const PolicyConfig& getCachedPolicyConfig() {
static std::unique_ptr<PolicyConfig> policyConfig = [] {
auto config = std::make_unique<PolicyConfig>();
- environment->registerTearDown([] { policyConfig.reset(); });
return config;
}();
return *policyConfig;
}
-class AudioPolicyConfigTest : public HidlTestBase {
- public:
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(HidlTestBase::SetUp()); // setup base
- auto& policyConfig = getCachedPolicyConfig();
- ASSERT_EQ(0, policyConfig.getStatus()) << policyConfig.getError();
- }
-};
-
-TEST_F(AudioPolicyConfigTest, LoadAudioPolicyXMLConfiguration) {
- doc::test("Test parsing audio_policy_configuration.xml (called in SetUp)");
-}
-
-TEST_F(AudioPolicyConfigTest, HasPrimaryModule) {
- auto& policyConfig = getCachedPolicyConfig();
- ASSERT_TRUE(policyConfig.getPrimaryModule() != nullptr)
- << "Could not find primary module in configuration file: "
- << policyConfig.getFilePath();
-}
-
//////////////////////////////////////////////////////////////////////////////
//////////////////// Test parameter types and definitions ////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -290,53 +228,59 @@
static inline std::string DeviceParameterToString(
const ::testing::TestParamInfo<DeviceParameter>& info) {
const auto& deviceName = std::get<PARAM_DEVICE_NAME>(info.param);
-#if MAJOR_VERSION <= 5
- return !deviceName.empty() ? deviceName : std::to_string(info.index);
-#elif MAJOR_VERSION >= 6
const auto factoryName =
::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
std::get<PARAM_FACTORY_NAME>(info.param), info.index});
return !deviceName.empty() ? factoryName + "_" + deviceName : factoryName;
-#endif
}
-#if MAJOR_VERSION <= 5
-// For V2..5 the factory is looked up using the instance name passed
-// in the environment, only one factory is returned. This is because the VTS
-// framework will call the test for each instance. Only the primary device of
-// the default service factory can be tested.
-
-// Return a pair of <"default", "primary"> or <[non-default name], "">
-// This is used to parametrize device factory tests.
-// The device name is used to indicate whether IPrimaryDevice is required.
-const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
- static std::vector<DeviceParameter> parameters = {
- {environment->getServiceName<IDevicesFactory>(),
- environment->getServiceName<IDevicesFactory>() == kDefaultServiceName
- ? DeviceManager::kPrimaryDevice
- : ""}};
- return parameters;
-}
-// Return a pair of <"default", "primary"> or nothing.
-// This is used to parametrize primary device tests.
-const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests() {
- static std::vector<DeviceParameter> parameters =
- !std::get<PARAM_DEVICE_NAME>(*getDeviceParametersForFactoryTests().begin()).empty()
- ? getDeviceParametersForFactoryTests()
- : std::vector<DeviceParameter>{};
- return parameters;
-}
-// In V2..5 device tests must only test the primary device.
-// No device tests are executed for non-primary devices.
const std::vector<DeviceParameter>& getDeviceParameters() {
- return getDeviceParametersForPrimaryDeviceTests();
+ static std::vector<DeviceParameter> parameters = [] {
+ std::vector<DeviceParameter> result;
+ const auto factories =
+ ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+ const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames();
+ result.reserve(devices.size());
+ for (const auto& factoryName : factories) {
+ for (const auto& deviceName : devices) {
+ if (DeviceManager::getInstance().get(factoryName, deviceName) != nullptr) {
+ result.emplace_back(factoryName, deviceName);
+ }
+ }
+ }
+ return result;
+ }();
+ return parameters;
}
-#elif MAJOR_VERSION >= 6
-// For V6 and above these functions are implemented in 6.0/AudioPrimaryHidlHalTest.cpp
-const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests();
-const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests();
-const std::vector<DeviceParameter>& getDeviceParameters();
-#endif
+
+const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
+ static std::vector<DeviceParameter> parameters = [] {
+ std::vector<DeviceParameter> result;
+ const auto factories =
+ ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+ for (const auto& factoryName : factories) {
+ result.emplace_back(factoryName,
+ DeviceManager::getInstance().getPrimary(factoryName) != nullptr
+ ? DeviceManager::kPrimaryDevice
+ : "");
+ }
+ return result;
+ }();
+ return parameters;
+}
+
+const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests() {
+ static std::vector<DeviceParameter> parameters = [] {
+ std::vector<DeviceParameter> result;
+ const auto primary = std::find_if(
+ getDeviceParameters().begin(), getDeviceParameters().end(), [](const auto& elem) {
+ return std::get<PARAM_DEVICE_NAME>(elem) == DeviceManager::kPrimaryDevice;
+ });
+ if (primary != getDeviceParameters().end()) result.push_back(*primary);
+ return result;
+ }();
+ return parameters;
+}
class AudioHidlTestWithDeviceParameter : public HidlTest,
public ::testing::WithParamInterface<DeviceParameter> {
@@ -349,6 +293,45 @@
}
};
+TEST(CheckConfig, audioPolicyConfigurationValidation) {
+ auto deviceParameters = getDeviceParametersForFactoryTests();
+ if (deviceParameters.size() == 0) {
+ GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no device parameter "
+ "is found.";
+ }
+ RecordProperty("description",
+ "Verify that the audio policy configuration file "
+ "is valid according to the schema");
+
+ const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
+ EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName,
+ android::audio_get_configuration_paths(), xsd);
+}
+
+class AudioPolicyConfigTest : public AudioHidlTestWithDeviceParameter {
+ public:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp()); // setup base
+ auto& policyConfig = getCachedPolicyConfig();
+ ASSERT_EQ(0, policyConfig.getStatus()) << policyConfig.getError();
+ }
+};
+
+TEST_P(AudioPolicyConfigTest, LoadAudioPolicyXMLConfiguration) {
+ doc::test("Test parsing audio_policy_configuration.xml (called in SetUp)");
+}
+
+TEST_P(AudioPolicyConfigTest, HasPrimaryModule) {
+ auto& policyConfig = getCachedPolicyConfig();
+ ASSERT_TRUE(policyConfig.getPrimaryModule() != nullptr)
+ << "Could not find primary module in configuration file: "
+ << policyConfig.getFilePath();
+}
+
+INSTANTIATE_TEST_CASE_P(AudioHidl, AudioPolicyConfigTest,
+ ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
+ &DeviceParameterToString);
+
//////////////////////////////////////////////////////////////////////////////
////////////////////// getService audio_devices_factory //////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -1576,20 +1559,3 @@
testAccessors<OPTIONAL>("HAC", Initial{false}, {true}, &IPrimaryDevice::setHacEnabled,
&IPrimaryDevice::getHacEnabled);
}
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////// Clean caches on global tear down ////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-int main(int argc, char** argv) {
- environment = new AudioHidlTestEnvironment;
- // For V2..5 it's critical to initialize environment before GTest.
- // The environment parses the service name from the command line,
- // then it can be used in GTest parameter generators which are
- // initialized during the call to InitGoogleTest.
- environment->init(&argc, argv);
- ::testing::AddGlobalTestEnvironment(environment);
- ::testing::InitGoogleTest(&argc, argv);
- int status = RUN_ALL_TESTS();
- return status;
-}
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index cb6584d..0c0727f 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -31,10 +31,6 @@
auto existing = instances.find(name);
if (existing != instances.end()) return existing->second;
auto [inserted, _] = instances.emplace(name, Derived::createInterfaceInstance(name));
- if (inserted->second) {
- environment->registerTearDown(
- [name]() { (void)Derived::getInstance().reset(name, false); });
- }
return inserted->second;
}
@@ -75,11 +71,7 @@
return instance;
}
static sp<IDevicesFactory> createInterfaceInstance(const std::string& name) {
-#if MAJOR_VERSION <= 5
- return ::testing::VtsHalHidlTargetTestBase::getService<IDevicesFactory>(name);
-#elif MAJOR_VERSION >= 6
return IDevicesFactory::getService(name);
-#endif
}
};
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV2_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV2_0TargetTest.xml
new file mode 100644
index 0000000..67fcdb6
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV2_0TargetTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalAudioV2_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="stop"/>
+ <option name="run-command" value="setprop vts.native_server.on 1"/>
+ <option name="teardown-command" value="start"/>
+ <option name="teardown-command" value="setprop vts.native_server.on 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="VtsHalAudioV2_0TargetTest" value="/data/local/tmp/VtsHalAudioV2_0TargetTest" />
+ <option name="push-file" key="audio_policy_configuration.xsd" value="/data/local/tmp/audio_policy_configuration_V2_0.xsd" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalAudioV2_0TargetTest" />
+ </test>
+</configuration>
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV4_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV4_0TargetTest.xml
new file mode 100644
index 0000000..2084060
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV4_0TargetTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalAudioV4_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="stop"/>
+ <option name="run-command" value="setprop vts.native_server.on 1"/>
+ <option name="teardown-command" value="start"/>
+ <option name="teardown-command" value="setprop vts.native_server.on 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="VtsHalAudioV4_0TargetTest" value="/data/local/tmp/VtsHalAudioV4_0TargetTest" />
+ <option name="push-file" key="audio_policy_configuration_V4_0.xsd" value="/data/local/tmp/audio_policy_configuration_V4_0.xsd" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalAudioV4_0TargetTest" />
+ </test>
+</configuration>
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV5_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV5_0TargetTest.xml
new file mode 100644
index 0000000..8b01e41
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV5_0TargetTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalAudioV5_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="stop"/>
+ <option name="run-command" value="setprop vts.native_server.on 1"/>
+ <option name="teardown-command" value="start"/>
+ <option name="teardown-command" value="setprop vts.native_server.on 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="VtsHalAudioV5_0TargetTest" value="/data/local/tmp/VtsHalAudioV5_0TargetTest" />
+ <option name="push-file" key="audio_policy_configuration_V5_0.xsd" value="/data/local/tmp/audio_policy_configuration_V5_0.xsd" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalAudioV5_0TargetTest" />
+ </test>
+</configuration>
diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 4ab572e..309aa9d 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -31,13 +31,13 @@
header_libs: [
"android.hardware.audio.common.util@all-versions",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
cc_test {
name: "VtsHalAudioEffectV2_0TargetTest",
defaults: ["VtsHalAudioEffectTargetTest_default"],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioEffectV2_0TargetTest.xml",
static_libs: [
@@ -57,7 +57,7 @@
cc_test {
name: "VtsHalAudioEffectV4_0TargetTest",
defaults: ["VtsHalAudioEffectTargetTest_default"],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioEffectV4_0TargetTest.xml",
static_libs: [
@@ -77,7 +77,7 @@
cc_test {
name: "VtsHalAudioEffectV5_0TargetTest",
defaults: ["VtsHalAudioEffectTargetTest_default"],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioEffectV5_0TargetTest.xml",
static_libs: [
@@ -97,7 +97,7 @@
cc_test {
name: "VtsHalAudioEffectV6_0TargetTest",
defaults: ["VtsHalAudioEffectTargetTest_default"],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioEffectV6_0TargetTest.xml",
static_libs: [
diff --git a/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp b/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp
index 9c0135b..f251634 100644
--- a/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp
+++ b/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp
@@ -18,6 +18,7 @@
#include <iterator>
#include <media/EffectsConfig.h>
+#include <system/audio_config.h>
// clang-format off
#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
// clang-format on
@@ -41,13 +42,14 @@
GTEST_SKIP() << "No Effects HAL version " STRINGIFY(CPP_VERSION) " on this device";
}
- std::vector<const char*> locations(std::begin(DEFAULT_LOCATIONS), std::end(DEFAULT_LOCATIONS));
const char* xsd = "/data/local/tmp/audio_effects_conf_" STRINGIFY(CPP_VERSION) ".xsd";
#if MAJOR_VERSION == 2
// In V2, audio effect XML is not required. .conf is still allowed though deprecated
- EXPECT_VALID_XML_MULTIPLE_LOCATIONS(DEFAULT_NAME, locations, xsd);
+ EXPECT_VALID_XML_MULTIPLE_LOCATIONS(DEFAULT_NAME, android::audio_get_configuration_paths(),
+ xsd);
#elif MAJOR_VERSION >= 4
// Starting with V4, audio effect XML is required
- EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(DEFAULT_NAME, locations, xsd);
+ EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(DEFAULT_NAME, android::audio_get_configuration_paths(),
+ xsd);
#endif
}
diff --git a/audio/policy/1.0/vts/functional/Android.bp b/audio/policy/1.0/vts/functional/Android.bp
index b50e501..a5ddee5 100644
--- a/audio/policy/1.0/vts/functional/Android.bp
+++ b/audio/policy/1.0/vts/functional/Android.bp
@@ -24,7 +24,7 @@
shared_libs: [
"libaudiofoundation",
],
- // Use test_config for vts-core suite.
+ // Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
test_config: "VtsHalAudioPolicyV1_0TargetTest.xml",
cflags: [
@@ -54,6 +54,6 @@
gtest: true,
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/audio/policy/1.0/vts/functional/ValidateEngineConfiguration.cpp b/audio/policy/1.0/vts/functional/ValidateEngineConfiguration.cpp
index a0aaa6e..5741fa9 100644
--- a/audio/policy/1.0/vts/functional/ValidateEngineConfiguration.cpp
+++ b/audio/policy/1.0/vts/functional/ValidateEngineConfiguration.cpp
@@ -23,7 +23,8 @@
#include <string>
#include "utility/ValidateXml.h"
-static const std::vector<const char*> locations = {"/odm/etc", "/vendor/etc", "/system/etc"};
+#include <system/audio_config.h>
+
static const std::string config = "audio_policy_engine_configuration.xml";
static const std::string schema =
std::string(XSD_DIR) + "/audio_policy_engine_configuration_V1_0.xsd";
@@ -42,7 +43,8 @@
RecordProperty("description",
"Verify that the audio policy engine configuration file "
"is valid according to the schemas");
- EXPECT_VALID_XML_MULTIPLE_LOCATIONS(config.c_str(), locations, schema.c_str());
+ EXPECT_VALID_XML_MULTIPLE_LOCATIONS(config.c_str(), android::audio_get_configuration_paths(),
+ schema.c_str());
}
/**
@@ -52,9 +54,11 @@
*/
static bool deviceUsesConfigurableEngine() {
return android::hardware::audio::common::test::utility::validateXmlMultipleLocations<true>(
- "", "", "", config.c_str(), locations, schema.c_str()) &&
+ "", "", "", config.c_str(), android::audio_get_configuration_paths(),
+ schema.c_str()) &&
android::hardware::audio::common::test::utility::validateXmlMultipleLocations<true>(
- "", "", "", configurableConfig.c_str(), locations, configurableSchemas.c_str());
+ "", "", "", configurableConfig.c_str(), android::audio_get_configuration_paths(),
+ configurableSchemas.c_str());
}
TEST(ValidateConfiguration, audioPolicyEngineConfigurable) {
diff --git a/authsecret/1.0/vts/functional/Android.bp b/authsecret/1.0/vts/functional/Android.bp
index 9ce9cda..c49d374 100644
--- a/authsecret/1.0/vts/functional/Android.bp
+++ b/authsecret/1.0/vts/functional/Android.bp
@@ -21,7 +21,7 @@
static_libs: ["android.hardware.authsecret@1.0"],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
require_root: true,
}
diff --git a/automotive/audiocontrol/1.0/vts/functional/Android.bp b/automotive/audiocontrol/1.0/vts/functional/Android.bp
index 3cb6340..1bb8e88 100644
--- a/automotive/audiocontrol/1.0/vts/functional/Android.bp
+++ b/automotive/audiocontrol/1.0/vts/functional/Android.bp
@@ -25,5 +25,8 @@
static_libs: [
"android.hardware.automotive.audiocontrol@1.0",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
diff --git a/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
index fc0deb9..de1ec02 100644
--- a/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
+++ b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
@@ -25,11 +25,12 @@
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
-#include <android/hardware/automotive/audiocontrol/1.0/types.h>
#include <android/hardware/automotive/audiocontrol/1.0/IAudioControl.h>
+#include <android/hardware/automotive/audiocontrol/1.0/types.h>
#include <android/log.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
using namespace ::android::hardware::automotive::audiocontrol::V1_0;
using ::android::hardware::Return;
@@ -40,30 +41,12 @@
using ::android::hardware::hidl_vec;
using ::android::sp;
-
-// Boiler plate for test harness
-class CarAudioControlHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static CarAudioControlHidlEnvironment* Instance() {
- static CarAudioControlHidlEnvironment* instance = new CarAudioControlHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override { registerTestService<IAudioControl>(); }
- private:
- CarAudioControlHidlEnvironment() {}
-};
-
-
// The main test class for the automotive AudioControl HAL
-class CarAudioControlHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-public:
+class CarAudioControlHidlTest : public ::testing::TestWithParam<std::string> {
+ public:
virtual void SetUp() override {
// Make sure we can connect to the driver
- pAudioControl = ::testing::VtsHalHidlTargetTestBase::getService<IAudioControl>(
- CarAudioControlHidlEnvironment::Instance()->
- getServiceName<IAudioControl>());
+ pAudioControl = IAudioControl::getService(GetParam());
ASSERT_NE(pAudioControl.get(), nullptr);
}
@@ -82,7 +65,7 @@
* fader actually works. The only thing we can do is exercise the HAL and if the HAL crashes,
* we _might_ get a test failure if that breaks the connection to the driver.
*/
-TEST_F(CarAudioControlHidlTest, FaderExercise) {
+TEST_P(CarAudioControlHidlTest, FaderExercise) {
ALOGI("Fader exercise test (silent)");
// Set the fader all the way to the back
@@ -104,7 +87,7 @@
/*
* Balance exercise test.
*/
-TEST_F(CarAudioControlHidlTest, BalanceExercise) {
+TEST_P(CarAudioControlHidlTest, BalanceExercise) {
ALOGI("Balance exercise test (silent)");
// Set the balance all the way to the left
@@ -126,7 +109,7 @@
/*
* Context mapping test.
*/
-TEST_F(CarAudioControlHidlTest, ContextMapping) {
+TEST_P(CarAudioControlHidlTest, ContextMapping) {
ALOGI("Context mapping test");
int bus = -1;
@@ -156,3 +139,8 @@
bus = pAudioControl->getBusForContext((ContextNumber)~0);
EXPECT_EQ(bus, -1);
}
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, CarAudioControlHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IAudioControl::descriptor)),
+ android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/automotive/audiocontrol/2.0/default/AudioControl.cpp b/automotive/audiocontrol/2.0/default/AudioControl.cpp
index 6505e34..b7c11cd 100644
--- a/automotive/audiocontrol/2.0/default/AudioControl.cpp
+++ b/automotive/audiocontrol/2.0/default/AudioControl.cpp
@@ -1,12 +1,42 @@
+/*
+ * 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 "AudioControl.h"
+#include <stdio.h>
+
#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+
#include <hidl/HidlTransportSupport.h>
+#include <hwbinder/IPCThreadState.h>
+#include <private/android_filesystem_config.h>
#include "CloseHandle.h"
namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
+using ::android::base::EqualsIgnoreCase;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+
+static const float kLowerBound = -1.0f;
+static const float kUpperBound = 1.0f;
+
AudioControl::AudioControl() {}
Return<sp<ICloseHandle>> AudioControl::registerFocusListener(const sp<IFocusListener>& listener) {
@@ -29,27 +59,29 @@
}
Return<void> AudioControl::setBalanceTowardRight(float value) {
- // For completeness, lets bounds check the input...
if (isValidValue(value)) {
- LOG(ERROR) << "Balance value out of range -1 to 1 at " << value;
- } else {
// Just log in this default mock implementation
LOG(INFO) << "Balance set to " << value;
+ } else {
+ LOG(ERROR) << "Balance value out of range -1 to 1 at " << value;
}
return Void();
}
Return<void> AudioControl::setFadeTowardFront(float value) {
- // For completeness, lets bounds check the input...
if (isValidValue(value)) {
- LOG(ERROR) << "Fader value out of range -1 to 1 at " << value;
- } else {
// Just log in this default mock implementation
LOG(INFO) << "Fader set to " << value;
+ } else {
+ LOG(ERROR) << "Fader value out of range -1 to 1 at " << value;
}
return Void();
}
+bool AudioControl::isValidValue(float value) {
+ return (value > kLowerBound) && (value < kUpperBound);
+}
+
Return<void> AudioControl::onAudioFocusChange(hidl_bitfield<AudioUsage> usage, int zoneId,
hidl_bitfield<AudioFocusChange> focusChange) {
LOG(INFO) << "Focus changed: " << static_cast<int>(focusChange) << " for usage "
@@ -57,4 +89,132 @@
return Void();
}
+Return<void> AudioControl::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ if (fd.getNativeHandle() == nullptr || fd->numFds == 0) {
+ LOG(ERROR) << "Invalid parameters passed to debug()";
+ return Void();
+ }
+
+ cmdDump(fd->data[0], options);
+ return Void();
+}
+
+void AudioControl::cmdDump(int fd, const hidl_vec<hidl_string>& options) {
+ if (options.size() == 0) {
+ dump(fd);
+ return;
+ }
+
+ std::string option = options[0];
+ if (EqualsIgnoreCase(option, "--help")) {
+ cmdHelp(fd);
+ } else if (EqualsIgnoreCase(option, "--request")) {
+ cmdRequestFocus(fd, options);
+ } else if (EqualsIgnoreCase(option, "--abandon")) {
+ cmdAbandonFocus(fd, options);
+ } else {
+ dprintf(fd, "Invalid option: %s\n", option.c_str());
+ }
+}
+
+void AudioControl::dump(int fd) {
+ if (mFocusListener == nullptr) {
+ dprintf(fd, "No focus listener registered\n");
+ } else {
+ dprintf(fd, "Focus listener registered\n");
+ }
+}
+
+void AudioControl::cmdHelp(int fd) const {
+ dprintf(fd, "Usage: \n\n");
+ dprintf(fd, "[no args]: dumps focus listener status\n");
+ dprintf(fd, "--help: shows this help\n");
+ dprintf(fd,
+ "--request <USAGE> <ZONE_ID> <FOCUS_GAIN>: requests audio focus for specified "
+ "usage (int), audio zone ID (int), and focus gain type (int)\n");
+ dprintf(fd,
+ "--abandon <USAGE> <ZONE_ID>: abandons audio focus for specified usage (int) and "
+ "audio zone ID (int)\n");
+}
+
+void AudioControl::cmdRequestFocus(int fd, const hidl_vec<hidl_string>& options) {
+ if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
+
+ hidl_bitfield<AudioUsage> usage;
+ if (!safelyParseInt(options[1], &usage)) {
+ dprintf(fd, "Non-integer usage provided with request: %s\n", options[1].c_str());
+ return;
+ }
+ int zoneId;
+ if (!safelyParseInt(options[2], &zoneId)) {
+ dprintf(fd, "Non-integer zoneId provided with request: %s\n", options[2].c_str());
+ return;
+ }
+ hidl_bitfield<AudioFocusChange> focusGain;
+ if (!safelyParseInt(options[3], &focusGain)) {
+ dprintf(fd, "Non-integer focusGain provided with request: %s\n", options[3].c_str());
+ return;
+ }
+
+ if (mFocusListener == nullptr) {
+ dprintf(fd, "Unable to request focus - no focus listener registered\n");
+ return;
+ }
+
+ mFocusListener->requestAudioFocus(usage, zoneId, focusGain);
+ dprintf(fd, "Requested focus for usage %d, zoneId %d, and focusGain %d\n", usage, zoneId,
+ focusGain);
+}
+
+void AudioControl::cmdAbandonFocus(int fd, const hidl_vec<hidl_string>& options) {
+ if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 2)) return;
+
+ hidl_bitfield<AudioUsage> usage;
+ if (!safelyParseInt(options[1], &usage)) {
+ dprintf(fd, "Non-integer usage provided with abandon: %s\n", options[1].c_str());
+ return;
+ }
+ int zoneId;
+ if (!safelyParseInt(options[2], &zoneId)) {
+ dprintf(fd, "Non-integer zoneId provided with abandon: %s\n", options[2].c_str());
+ return;
+ }
+
+ if (mFocusListener == nullptr) {
+ dprintf(fd, "Unable to abandon focus - no focus listener registered\n");
+ return;
+ }
+
+ mFocusListener->abandonAudioFocus(usage, zoneId);
+ dprintf(fd, "Abandoned focus for usage %d and zoneId %d\n", usage, zoneId);
+}
+
+bool AudioControl::checkCallerHasWritePermissions(int fd) {
+ // Double check that's only called by root - it should be be blocked at the HIDL debug() level,
+ // but it doesn't hurt to make sure...
+ if (hardware::IPCThreadState::self()->getCallingUid() != AID_ROOT) {
+ dprintf(fd, "Must be root\n");
+ return false;
+ }
+ return true;
+}
+
+bool AudioControl::checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options,
+ size_t expectedSize) {
+ // options includes the command, so reducing size by one
+ size_t size = options.size() - 1;
+ if (size == expectedSize) {
+ return true;
+ }
+ dprintf(fd, "Invalid number of arguments: required %zu, got %zu\n", expectedSize, size);
+ return false;
+}
+
+bool AudioControl::safelyParseInt(std::string s, int* out) {
+ if (!android::base::ParseInt(s, out)) {
+ return false;
+ }
+ return true;
+}
+
} // namespace android::hardware::automotive::audiocontrol::V2_0::implementation
diff --git a/automotive/audiocontrol/2.0/default/AudioControl.h b/automotive/audiocontrol/2.0/default/AudioControl.h
index 475a693..d66458e 100644
--- a/automotive/audiocontrol/2.0/default/AudioControl.h
+++ b/automotive/audiocontrol/2.0/default/AudioControl.h
@@ -35,13 +35,24 @@
hidl_bitfield<AudioFocusChange> focusChange);
Return<void> setBalanceTowardRight(float value) override;
Return<void> setFadeTowardFront(float value) override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Implementation details
AudioControl();
private:
sp<IFocusListener> mFocusListener;
- static bool isValidValue(float value) { return (value > 1.0f) || (value < -1.0f); }
+
+ static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
+ static bool checkCallerHasWritePermissions(int fd);
+ static bool isValidValue(float value);
+ static bool safelyParseInt(std::string s, int* out);
+
+ void cmdDump(int fd, const hidl_vec<hidl_string>& options);
+ void cmdHelp(int fd) const;
+ void cmdRequestFocus(int fd, const hidl_vec<hidl_string>& options);
+ void cmdAbandonFocus(int fd, const hidl_vec<hidl_string>& options);
+ void dump(int fd);
};
} // namespace android::hardware::automotive::audiocontrol::V2_0::implementation
diff --git a/automotive/audiocontrol/2.0/types.hal b/automotive/audiocontrol/2.0/types.hal
index 65b0988..80d9ee1 100644
--- a/automotive/audiocontrol/2.0/types.hal
+++ b/automotive/audiocontrol/2.0/types.hal
@@ -19,7 +19,7 @@
/**
* Changes in audio focus that can be experienced
*/
-enum AudioFocusChange : uint32_t {
+enum AudioFocusChange : int32_t {
NONE = 0,
GAIN = 1,
GAIN_TRANSIENT = 2,
diff --git a/automotive/audiocontrol/2.0/vts/functional/Android.bp b/automotive/audiocontrol/2.0/vts/functional/Android.bp
index 520b042..ac20509 100644
--- a/automotive/audiocontrol/2.0/vts/functional/Android.bp
+++ b/automotive/audiocontrol/2.0/vts/functional/Android.bp
@@ -24,6 +24,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/automotive/can/1.0/default/CanController.cpp b/automotive/can/1.0/default/CanController.cpp
index a2643af..9c0f2c5 100644
--- a/automotive/can/1.0/default/CanController.cpp
+++ b/automotive/can/1.0/default/CanController.cpp
@@ -23,7 +23,7 @@
#include <android-base/logging.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
-#include <filesystem>
+#include <automotive/filesystem>
#include <fstream>
#include <regex>
@@ -31,6 +31,7 @@
using IfId = ICanController::BusConfig::InterfaceId;
using IfIdDisc = ICanController::BusConfig::InterfaceId::hidl_discriminator;
+namespace fs = android::hardware::automotive::filesystem;
namespace fsErrors {
static const std::error_code ok;
@@ -42,10 +43,10 @@
/* In the /sys/devices tree, there are files called "serial", which contain the serial numbers
* for various devices. The exact location inside of this directory is dependent upon the
* hardware we are running on, so we have to start from /sys/devices and work our way down. */
-static const std::filesystem::path kDevPath("/sys/devices/");
+static const fs::path kDevPath("/sys/devices/");
static const std::regex kTtyRe("^tty[A-Z]+[0-9]+$");
-static constexpr auto kOpts = ~(std::filesystem::directory_options::follow_directory_symlink |
- std::filesystem::directory_options::skip_permission_denied);
+static constexpr auto kOpts = ~(fs::directory_options::follow_directory_symlink |
+ fs::directory_options::skip_permission_denied);
/**
* A helper object to associate the interface name and type of a USB to CAN adapter.
@@ -72,16 +73,16 @@
* \param serialPath - Absolute path to a "serial" file for a given device in /sys.
* \return A populated UsbCanIface. On failure, nullopt is returned.
*/
-static std::optional<UsbCanIface> getIfaceName(std::filesystem::path serialPath) {
+static std::optional<UsbCanIface> getIfaceName(fs::path serialPath) {
std::error_code fsStatus;
// Since the path is to a file called "serial", we need to search its parent directory.
- std::filesystem::recursive_directory_iterator fsItr(serialPath.parent_path(), kOpts, fsStatus);
+ fs::recursive_directory_iterator fsItr(serialPath.parent_path(), kOpts, fsStatus);
if (fsStatus != fsErrors::ok) {
LOG(ERROR) << "Failed to open " << serialPath.parent_path();
return std::nullopt;
}
- for (; fsStatus == fsErrors::ok && fsItr != std::filesystem::recursive_directory_iterator();
+ for (; fsStatus == fsErrors::ok && fsItr != fs::recursive_directory_iterator();
fsItr.increment(fsStatus)) {
/* We want either a directory called "net" or a directory that looks like tty<something>, so
* skip files. */
@@ -95,7 +96,7 @@
if (currentDir == "net") {
/* This device is a SocketCAN device. The iface name is the only directory under
* net/. Multiple directories under net/ is an error.*/
- std::filesystem::directory_iterator netItr(fsItr->path(), kOpts, fsStatus);
+ fs::directory_iterator netItr(fsItr->path(), kOpts, fsStatus);
if (fsStatus != fsErrors::ok) {
LOG(ERROR) << "Failed to open " << fsItr->path() << " to get net name!";
return std::nullopt;
@@ -111,7 +112,7 @@
LOG(ERROR) << "Failed to verify " << fsItr->path() << " has valid net name!";
return std::nullopt;
}
- if (netItr != std::filesystem::directory_iterator()) {
+ if (netItr != fs::directory_iterator()) {
// There should never be more than one name under net/
LOG(ERROR) << "Found more than one net name in " << fsItr->path() << "!";
return std::nullopt;
@@ -157,13 +158,13 @@
*/
static std::optional<UsbCanIface> findUsbDevice(const hidl_vec<hidl_string>& configSerialnos) {
std::error_code fsStatus;
- std::filesystem::recursive_directory_iterator fsItr(kDevPath, kOpts, fsStatus);
+ fs::recursive_directory_iterator fsItr(kDevPath, kOpts, fsStatus);
if (fsStatus != fsErrors::ok) {
LOG(ERROR) << "Failed to open " << kDevPath;
return std::nullopt;
}
- for (; fsStatus == fsErrors::ok && fsItr != std::filesystem::recursive_directory_iterator();
+ for (; fsStatus == fsErrors::ok && fsItr != fs::recursive_directory_iterator();
fsItr.increment(fsStatus)) {
// We want to find a file called "serial", which is in a directory somewhere. Skip files.
bool isDir = fsItr->is_directory(fsStatus);
@@ -174,7 +175,7 @@
if (!isDir) continue;
auto serialnoPath = fsItr->path() / "serial";
- bool isReg = std::filesystem::is_regular_file(serialnoPath, fsStatus);
+ bool isReg = fs::is_regular_file(serialnoPath, fsStatus);
/* Make sure we have permissions to this directory, ignore enoent, since the file
* "serial" may not exist, which is ok. */
diff --git a/automotive/can/1.0/default/libc++fs/.clang-format b/automotive/can/1.0/default/libc++fs/.clang-format
new file mode 100644
index 0000000..dd59681
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: LLVM
+
+---
+Language: Cpp
+Standard: Cpp03
+
+AlwaysBreakTemplateDeclarations: true
+PointerAlignment: Left
+
+# Disable formatting options which may break tests.
+SortIncludes: false
+ReflowComments: false
+---
diff --git a/automotive/can/1.0/default/libc++fs/Android.bp b/automotive/can/1.0/default/libc++fs/Android.bp
index 1fe324e..7ab1c28 100644
--- a/automotive/can/1.0/default/libc++fs/Android.bp
+++ b/automotive/can/1.0/default/libc++fs/Android.bp
@@ -19,7 +19,6 @@
cc_defaults {
name: "android.hardware.automotive@libc++fsdefaults",
- host_supported: true,
local_include_dirs: ["include"],
export_include_dirs: ["include"],
cflags: [
@@ -28,33 +27,12 @@
"-Wno-unused-parameter",
],
cppflags: [
- "-std=c++14",
+ "-std=c++17",
"-fexceptions",
"-DLIBCXX_BUILDING_LIBCXXABI",
"-D_LIBCPP_BUILDING_LIBRARY",
],
rtti: true,
- stl: "none",
- target: {
- linux_bionic: {
- enabled: true,
- },
- windows: {
- enabled: true,
- cflags: [
- "-D_LIBCPP_HAS_THREAD_API_WIN32",
- "-D_LIBCXXABI_BUILDING_LIBRARY",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-UWIN32_LEAN_AND_MEAN",
- ],
- },
- windows_x86: {
- cflags: [
- "-fsjlj-exceptions",
- ],
- },
- },
}
cc_library_static {
diff --git a/automotive/can/1.0/default/libc++fs/include b/automotive/can/1.0/default/libc++fs/include
deleted file mode 120000
index 346e659..0000000
--- a/automotive/can/1.0/default/libc++fs/include
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../../external/libcxx/include/
\ No newline at end of file
diff --git a/automotive/can/1.0/default/libc++fs/include/automotive/filesystem b/automotive/can/1.0/default/libc++fs/include/automotive/filesystem
new file mode 100644
index 0000000..660ad09
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/include/automotive/filesystem
@@ -0,0 +1,2699 @@
+// -*- C++ -*-
+//===--------------------------- filesystem -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef _LIBAUTO_FILESYSTEM
+#define _LIBAUTO_FILESYSTEM
+/*
+ filesystem synopsis
+
+ namespace android::hardware::automotive { namespace filesystem {
+
+ class path;
+
+ void swap(path& lhs, path& rhs) noexcept;
+ size_t hash_value(const path& p) noexcept;
+
+ bool operator==(const path& lhs, const path& rhs) noexcept;
+ bool operator!=(const path& lhs, const path& rhs) noexcept;
+ bool operator< (const path& lhs, const path& rhs) noexcept;
+ bool operator<=(const path& lhs, const path& rhs) noexcept;
+ bool operator> (const path& lhs, const path& rhs) noexcept;
+ bool operator>=(const path& lhs, const path& rhs) noexcept;
+
+ path operator/ (const path& lhs, const path& rhs);
+
+ // fs.path.io operators are friends of path.
+ template <class charT, class traits>
+ friend basic_ostream<charT, traits>&
+ operator<<(basic_ostream<charT, traits>& os, const path& p);
+
+ template <class charT, class traits>
+ friend basic_istream<charT, traits>&
+ operator>>(basic_istream<charT, traits>& is, path& p);
+
+ template <class Source>
+ path u8path(const Source& source);
+ template <class InputIterator>
+ path u8path(InputIterator first, InputIterator last);
+
+ class filesystem_error;
+ class directory_entry;
+
+ class directory_iterator;
+
+ // enable directory_iterator range-based for statements
+ directory_iterator begin(directory_iterator iter) noexcept;
+ directory_iterator end(const directory_iterator&) noexcept;
+
+ class recursive_directory_iterator;
+
+ // enable recursive_directory_iterator range-based for statements
+ recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
+ recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
+
+ class file_status;
+
+ struct space_info
+ {
+ uintmax_t capacity;
+ uintmax_t free;
+ uintmax_t available;
+ };
+
+ enum class file_type;
+ enum class perms;
+ enum class perm_options;
+ enum class copy_options;
+ enum class directory_options;
+
+ typedef chrono::time_point<trivial-clock> file_time_type;
+
+ // operational functions
+
+ path absolute(const path& p);
+ path absolute(const path& p, error_code &ec);
+
+ path canonical(const path& p);
+ path canonical(const path& p, error_code& ec);
+
+ void copy(const path& from, const path& to);
+ void copy(const path& from, const path& to, error_code& ec);
+ void copy(const path& from, const path& to, copy_options options);
+ void copy(const path& from, const path& to, copy_options options,
+ error_code& ec);
+
+ bool copy_file(const path& from, const path& to);
+ bool copy_file(const path& from, const path& to, error_code& ec);
+ bool copy_file(const path& from, const path& to, copy_options option);
+ bool copy_file(const path& from, const path& to, copy_options option,
+ error_code& ec);
+
+ void copy_symlink(const path& existing_symlink, const path& new_symlink);
+ void copy_symlink(const path& existing_symlink, const path& new_symlink,
+ error_code& ec) noexcept;
+
+ bool create_directories(const path& p);
+ bool create_directories(const path& p, error_code& ec);
+
+ bool create_directory(const path& p);
+ bool create_directory(const path& p, error_code& ec) noexcept;
+
+ bool create_directory(const path& p, const path& attributes);
+ bool create_directory(const path& p, const path& attributes,
+ error_code& ec) noexcept;
+
+ void create_directory_symlink(const path& to, const path& new_symlink);
+ void create_directory_symlink(const path& to, const path& new_symlink,
+ error_code& ec) noexcept;
+
+ void create_hard_link(const path& to, const path& new_hard_link);
+ void create_hard_link(const path& to, const path& new_hard_link,
+ error_code& ec) noexcept;
+
+ void create_symlink(const path& to, const path& new_symlink);
+ void create_symlink(const path& to, const path& new_symlink,
+ error_code& ec) noexcept;
+
+ path current_path();
+ path current_path(error_code& ec);
+ void current_path(const path& p);
+ void current_path(const path& p, error_code& ec) noexcept;
+
+ bool exists(file_status s) noexcept;
+ bool exists(const path& p);
+ bool exists(const path& p, error_code& ec) noexcept;
+
+ bool equivalent(const path& p1, const path& p2);
+ bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
+
+ uintmax_t file_size(const path& p);
+ uintmax_t file_size(const path& p, error_code& ec) noexcept;
+
+ uintmax_t hard_link_count(const path& p);
+ uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
+
+ bool is_block_file(file_status s) noexcept;
+ bool is_block_file(const path& p);
+ bool is_block_file(const path& p, error_code& ec) noexcept;
+
+ bool is_character_file(file_status s) noexcept;
+ bool is_character_file(const path& p);
+ bool is_character_file(const path& p, error_code& ec) noexcept;
+
+ bool is_directory(file_status s) noexcept;
+ bool is_directory(const path& p);
+ bool is_directory(const path& p, error_code& ec) noexcept;
+
+ bool is_empty(const path& p);
+ bool is_empty(const path& p, error_code& ec) noexcept;
+
+ bool is_fifo(file_status s) noexcept;
+ bool is_fifo(const path& p);
+ bool is_fifo(const path& p, error_code& ec) noexcept;
+
+ bool is_other(file_status s) noexcept;
+ bool is_other(const path& p);
+ bool is_other(const path& p, error_code& ec) noexcept;
+
+ bool is_regular_file(file_status s) noexcept;
+ bool is_regular_file(const path& p);
+ bool is_regular_file(const path& p, error_code& ec) noexcept;
+
+ bool is_socket(file_status s) noexcept;
+ bool is_socket(const path& p);
+ bool is_socket(const path& p, error_code& ec) noexcept;
+
+ bool is_symlink(file_status s) noexcept;
+ bool is_symlink(const path& p);
+ bool is_symlink(const path& p, error_code& ec) noexcept;
+
+ file_time_type last_write_time(const path& p);
+ file_time_type last_write_time(const path& p, error_code& ec) noexcept;
+ void last_write_time(const path& p, file_time_type new_time);
+ void last_write_time(const path& p, file_time_type new_time,
+ error_code& ec) noexcept;
+
+ void permissions(const path& p, perms prms,
+ perm_options opts=perm_options::replace);
+ void permissions(const path& p, perms prms, error_code& ec) noexcept;
+ void permissions(const path& p, perms prms, perm_options opts,
+ error_code& ec);
+
+ path proximate(const path& p, error_code& ec);
+ path proximate(const path& p, const path& base = current_path());
+ path proximate(const path& p, const path& base, error_code &ec);
+
+ path read_symlink(const path& p);
+ path read_symlink(const path& p, error_code& ec);
+
+ path relative(const path& p, error_code& ec);
+ path relative(const path& p, const path& base=current_path());
+ path relative(const path& p, const path& base, error_code& ec);
+
+ bool remove(const path& p);
+ bool remove(const path& p, error_code& ec) noexcept;
+
+ uintmax_t remove_all(const path& p);
+ uintmax_t remove_all(const path& p, error_code& ec);
+
+ void rename(const path& from, const path& to);
+ void rename(const path& from, const path& to, error_code& ec) noexcept;
+
+ void resize_file(const path& p, uintmax_t size);
+ void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
+
+ space_info space(const path& p);
+ space_info space(const path& p, error_code& ec) noexcept;
+
+ file_status status(const path& p);
+ file_status status(const path& p, error_code& ec) noexcept;
+
+ bool status_known(file_status s) noexcept;
+
+ file_status symlink_status(const path& p);
+ file_status symlink_status(const path& p, error_code& ec) noexcept;
+
+ path temp_directory_path();
+ path temp_directory_path(error_code& ec);
+
+ path weakly_canonical(path const& p);
+ path weakly_canonical(path const& p, error_code& ec);
+
+
+} } // namespace android::hardware::automotive::filesystem
+
+*/
+
+#include <__config>
+#include <cstddef>
+#include <cstdlib>
+#include <chrono>
+#include <iterator>
+#include <iosfwd>
+#include <locale>
+#include <memory>
+#include <stack>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <iomanip> // for quoted
+#include <string_view>
+#include <version>
+
+#include <__debug>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#ifndef _LIBCPP_CXX03_LANG
+
+namespace android::hardware::automotive::filesystem {
+using namespace std;
+using namespace std::chrono;
+
+using std::basic_string;
+using std::enable_if;
+using std::error_code;
+using std::false_type;
+
+#ifndef _VSTD
+#define _LIBAUTO_UNDEF_VSTD
+#define _VSTD std
+#endif
+
+#ifdef _VSTD_FS
+#pragma push_macro("_VSTD_FS")
+#else
+#define _LIBAUTO_UNDEF_VSTD_FS
+#endif
+#define _VSTD_FS android::hardware::automotive::filesystem
+
+/* Begin copy of _FilesystemClock from include/chrono */
+struct _FilesystemClock {
+#if !defined(_LIBCPP_HAS_NO_INT128)
+ typedef __int128_t rep;
+ typedef nano period;
+#else
+ typedef long long rep;
+ typedef nano period;
+#endif
+
+ typedef chrono::duration<rep, period> duration;
+ typedef chrono::time_point<_FilesystemClock> time_point;
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false;
+
+ _LIBCPP_FUNC_VIS static time_point now() noexcept;
+
+ _LIBCPP_INLINE_VISIBILITY
+ static time_t to_time_t(const time_point& __t) noexcept {
+ typedef chrono::duration<rep> __secs;
+ return time_t(
+ chrono::duration_cast<__secs>(__t.time_since_epoch()).count());
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ static time_point from_time_t(time_t __t) noexcept {
+ typedef chrono::duration<rep> __secs;
+ return time_point(__secs(__t));
+ }
+};
+/* End copy of _FilesystemClock from include/chrono */
+
+typedef chrono::time_point<_FilesystemClock> file_time_type;
+
+struct _LIBCPP_TYPE_VIS space_info {
+ uintmax_t capacity;
+ uintmax_t free;
+ uintmax_t available;
+};
+
+enum class _LIBCPP_ENUM_VIS file_type : signed char {
+ none = 0,
+ not_found = -1,
+ regular = 1,
+ directory = 2,
+ symlink = 3,
+ block = 4,
+ character = 5,
+ fifo = 6,
+ socket = 7,
+ unknown = 8
+};
+
+enum class _LIBCPP_ENUM_VIS perms : unsigned {
+ none = 0,
+
+ owner_read = 0400,
+ owner_write = 0200,
+ owner_exec = 0100,
+ owner_all = 0700,
+
+ group_read = 040,
+ group_write = 020,
+ group_exec = 010,
+ group_all = 070,
+
+ others_read = 04,
+ others_write = 02,
+ others_exec = 01,
+ others_all = 07,
+
+ all = 0777,
+
+ set_uid = 04000,
+ set_gid = 02000,
+ sticky_bit = 01000,
+ mask = 07777,
+ unknown = 0xFFFF,
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator&(perms _LHS, perms _RHS) {
+ return static_cast<perms>(static_cast<unsigned>(_LHS) &
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator|(perms _LHS, perms _RHS) {
+ return static_cast<perms>(static_cast<unsigned>(_LHS) |
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator^(perms _LHS, perms _RHS) {
+ return static_cast<perms>(static_cast<unsigned>(_LHS) ^
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator~(perms _LHS) {
+ return static_cast<perms>(~static_cast<unsigned>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
+
+_LIBCPP_INLINE_VISIBILITY
+inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
+
+_LIBCPP_INLINE_VISIBILITY
+inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
+
+enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
+ replace = 1,
+ add = 2,
+ remove = 4,
+ nofollow = 8
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
+ return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
+ return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
+ return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator~(perm_options _LHS) {
+ return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
+ return _LHS = _LHS & _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
+ return _LHS = _LHS | _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
+ return _LHS = _LHS ^ _RHS;
+}
+
+enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
+ none = 0,
+ skip_existing = 1,
+ overwrite_existing = 2,
+ update_existing = 4,
+ recursive = 8,
+ copy_symlinks = 16,
+ skip_symlinks = 32,
+ directories_only = 64,
+ create_symlinks = 128,
+ create_hard_links = 256,
+ __in_recursive_copy = 512,
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
+ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
+ static_cast<unsigned short>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
+ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
+ static_cast<unsigned short>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
+ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
+ static_cast<unsigned short>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator~(copy_options _LHS) {
+ return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
+ return _LHS = _LHS & _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
+ return _LHS = _LHS | _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
+ return _LHS = _LHS ^ _RHS;
+}
+
+enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
+ none = 0,
+ follow_directory_symlink = 1,
+ skip_permission_denied = 2
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator&(directory_options _LHS,
+ directory_options _RHS) {
+ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
+ static_cast<unsigned char>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator|(directory_options _LHS,
+ directory_options _RHS) {
+ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
+ static_cast<unsigned char>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator^(directory_options _LHS,
+ directory_options _RHS) {
+ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
+ static_cast<unsigned char>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator~(directory_options _LHS) {
+ return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline directory_options& operator&=(directory_options& _LHS,
+ directory_options _RHS) {
+ return _LHS = _LHS & _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline directory_options& operator|=(directory_options& _LHS,
+ directory_options _RHS) {
+ return _LHS = _LHS | _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline directory_options& operator^=(directory_options& _LHS,
+ directory_options _RHS) {
+ return _LHS = _LHS ^ _RHS;
+}
+
+class _LIBCPP_TYPE_VIS file_status {
+public:
+ // constructors
+ _LIBCPP_INLINE_VISIBILITY
+ file_status() noexcept : file_status(file_type::none) {}
+ _LIBCPP_INLINE_VISIBILITY
+ explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
+ : __ft_(__ft),
+ __prms_(__prms) {}
+
+ file_status(const file_status&) noexcept = default;
+ file_status(file_status&&) noexcept = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ ~file_status() {}
+
+ file_status& operator=(const file_status&) noexcept = default;
+ file_status& operator=(file_status&&) noexcept = default;
+
+ // observers
+ _LIBCPP_INLINE_VISIBILITY
+ file_type type() const noexcept { return __ft_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ perms permissions() const noexcept { return __prms_; }
+
+ // modifiers
+ _LIBCPP_INLINE_VISIBILITY
+ void type(file_type __ft) noexcept { __ft_ = __ft; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void permissions(perms __p) noexcept { __prms_ = __p; }
+
+private:
+ file_type __ft_;
+ perms __prms_;
+};
+
+class _LIBCPP_TYPE_VIS directory_entry;
+
+template <class _Tp>
+struct __can_convert_char {
+ static const bool value = false;
+};
+template <class _Tp>
+struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
+template <>
+struct __can_convert_char<char> {
+ static const bool value = true;
+ using __char_type = char;
+};
+template <>
+struct __can_convert_char<wchar_t> {
+ static const bool value = true;
+ using __char_type = wchar_t;
+};
+template <>
+struct __can_convert_char<char16_t> {
+ static const bool value = true;
+ using __char_type = char16_t;
+};
+template <>
+struct __can_convert_char<char32_t> {
+ static const bool value = true;
+ using __char_type = char32_t;
+};
+
+template <class _ECharT>
+typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
+__is_separator(_ECharT __e) {
+ return __e == _ECharT('/');
+}
+
+struct _NullSentinal {};
+
+template <class _Tp>
+using _Void = void;
+
+template <class _Tp, class = void>
+struct __is_pathable_string : public false_type {};
+
+template <class _ECharT, class _Traits, class _Alloc>
+struct __is_pathable_string<
+ basic_string<_ECharT, _Traits, _Alloc>,
+ _Void<typename __can_convert_char<_ECharT>::__char_type> >
+ : public __can_convert_char<_ECharT> {
+ using _Str = basic_string<_ECharT, _Traits, _Alloc>;
+ using _Base = __can_convert_char<_ECharT>;
+ static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
+ static _ECharT const* __range_end(_Str const& __s) {
+ return __s.data() + __s.length();
+ }
+ static _ECharT __first_or_null(_Str const& __s) {
+ return __s.empty() ? _ECharT{} : __s[0];
+ }
+};
+
+template <class _ECharT, class _Traits>
+struct __is_pathable_string<
+ basic_string_view<_ECharT, _Traits>,
+ _Void<typename __can_convert_char<_ECharT>::__char_type> >
+ : public __can_convert_char<_ECharT> {
+ using _Str = basic_string_view<_ECharT, _Traits>;
+ using _Base = __can_convert_char<_ECharT>;
+ static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
+ static _ECharT const* __range_end(_Str const& __s) {
+ return __s.data() + __s.length();
+ }
+ static _ECharT __first_or_null(_Str const& __s) {
+ return __s.empty() ? _ECharT{} : __s[0];
+ }
+};
+
+template <class _Source, class _DS = typename decay<_Source>::type,
+ class _UnqualPtrType =
+ typename remove_const<typename remove_pointer<_DS>::type>::type,
+ bool _IsCharPtr = is_pointer<_DS>::value&&
+ __can_convert_char<_UnqualPtrType>::value>
+struct __is_pathable_char_array : false_type {};
+
+template <class _Source, class _ECharT, class _UPtr>
+struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
+ : __can_convert_char<typename remove_const<_ECharT>::type> {
+ using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
+
+ static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
+ static _ECharT const* __range_end(const _ECharT* __b) {
+ using _Iter = const _ECharT*;
+ const _ECharT __sentinal = _ECharT{};
+ _Iter __e = __b;
+ for (; *__e != __sentinal; ++__e)
+ ;
+ return __e;
+ }
+
+ static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
+};
+
+template <class _Iter, bool _IsIt = __is_input_iterator<_Iter>::value,
+ class = void>
+struct __is_pathable_iter : false_type {};
+
+template <class _Iter>
+struct __is_pathable_iter<
+ _Iter, true,
+ _Void<typename __can_convert_char<
+ typename iterator_traits<_Iter>::value_type>::__char_type> >
+ : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
+ using _ECharT = typename iterator_traits<_Iter>::value_type;
+ using _Base = __can_convert_char<_ECharT>;
+
+ static _Iter __range_begin(_Iter __b) { return __b; }
+ static _NullSentinal __range_end(_Iter) { return _NullSentinal{}; }
+
+ static _ECharT __first_or_null(_Iter __b) { return *__b; }
+};
+
+template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
+ bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
+ bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
+struct __is_pathable : false_type {
+ static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
+};
+
+template <class _Tp>
+struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
+
+template <class _Tp>
+struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
+};
+
+template <class _Tp>
+struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
+
+template <class _ECharT>
+struct _PathCVT {
+ static_assert(__can_convert_char<_ECharT>::value,
+ "Char type not convertible");
+
+ typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
+
+ static void __append_range(string& __dest, _ECharT const* __b,
+ _ECharT const* __e) {
+ _Narrower()(back_inserter(__dest), __b, __e);
+ }
+
+ template <class _Iter>
+ static void __append_range(string& __dest, _Iter __b, _Iter __e) {
+ static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
+ if (__b == __e)
+ return;
+ basic_string<_ECharT> __tmp(__b, __e);
+ _Narrower()(back_inserter(__dest), __tmp.data(),
+ __tmp.data() + __tmp.length());
+ }
+
+ template <class _Iter>
+ static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
+ static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
+ const _ECharT __sentinal = _ECharT{};
+ if (*__b == __sentinal)
+ return;
+ basic_string<_ECharT> __tmp;
+ for (; *__b != __sentinal; ++__b)
+ __tmp.push_back(*__b);
+ _Narrower()(back_inserter(__dest), __tmp.data(),
+ __tmp.data() + __tmp.length());
+ }
+
+ template <class _Source>
+ static void __append_source(string& __dest, _Source const& __s) {
+ using _Traits = __is_pathable<_Source>;
+ __append_range(__dest, _Traits::__range_begin(__s),
+ _Traits::__range_end(__s));
+ }
+};
+
+template <>
+struct _PathCVT<char> {
+
+ template <class _Iter>
+ static typename enable_if<__is_exactly_input_iterator<_Iter>::value>::type
+ __append_range(string& __dest, _Iter __b, _Iter __e) {
+ for (; __b != __e; ++__b)
+ __dest.push_back(*__b);
+ }
+
+ template <class _Iter>
+ static typename enable_if<__is_forward_iterator<_Iter>::value>::type
+ __append_range(string& __dest, _Iter __b, _Iter __e) {
+ __dest.__append_forward_unsafe(__b, __e);
+ }
+
+ template <class _Iter>
+ static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
+ const char __sentinal = char{};
+ for (; *__b != __sentinal; ++__b)
+ __dest.push_back(*__b);
+ }
+
+ template <class _Source>
+ static void __append_source(string& __dest, _Source const& __s) {
+ using _Traits = __is_pathable<_Source>;
+ __append_range(__dest, _Traits::__range_begin(__s),
+ _Traits::__range_end(__s));
+ }
+};
+
+class _LIBCPP_TYPE_VIS path {
+ template <class _SourceOrIter, class _Tp = path&>
+ using _EnableIfPathable =
+ typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
+
+ template <class _Tp>
+ using _SourceChar = typename __is_pathable<_Tp>::__char_type;
+
+ template <class _Tp>
+ using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
+
+public:
+ typedef char value_type;
+ typedef basic_string<value_type> string_type;
+ typedef _VSTD::string_view __string_view;
+ static constexpr value_type preferred_separator = '/';
+
+ enum class _LIBCPP_ENUM_VIS format : unsigned char {
+ auto_format,
+ native_format,
+ generic_format
+ };
+
+ // constructors and destructor
+ _LIBCPP_INLINE_VISIBILITY path() noexcept {}
+ _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
+ _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
+ : __pn_(_VSTD::move(__p.__pn_)) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ path(string_type&& __s, format = format::auto_format) noexcept
+ : __pn_(_VSTD::move(__s)) {}
+
+ template <class _Source, class = _EnableIfPathable<_Source, void> >
+ path(const _Source& __src, format = format::auto_format) {
+ _SourceCVT<_Source>::__append_source(__pn_, __src);
+ }
+
+ template <class _InputIt>
+ path(_InputIt __first, _InputIt __last, format = format::auto_format) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
+ }
+
+ // TODO Implement locale conversions.
+ template <class _Source, class = _EnableIfPathable<_Source, void> >
+ path(const _Source& __src, const locale& __loc, format = format::auto_format);
+ template <class _InputIt>
+ path(_InputIt __first, _InputIt _last, const locale& __loc,
+ format = format::auto_format);
+
+ _LIBCPP_INLINE_VISIBILITY
+ ~path() = default;
+
+ // assignments
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator=(const path& __p) {
+ __pn_ = __p.__pn_;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator=(path&& __p) noexcept {
+ __pn_ = _VSTD::move(__p.__pn_);
+ return *this;
+ }
+
+ template <class = void>
+ _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept {
+ __pn_ = _VSTD::move(__s);
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& assign(string_type&& __s) noexcept {
+ __pn_ = _VSTD::move(__s);
+ return *this;
+ }
+
+ template <class _Source>
+ _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
+ operator=(const _Source& __src) {
+ return this->assign(__src);
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> assign(const _Source& __src) {
+ __pn_.clear();
+ _SourceCVT<_Source>::__append_source(__pn_, __src);
+ return *this;
+ }
+
+ template <class _InputIt>
+ path& assign(_InputIt __first, _InputIt __last) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ __pn_.clear();
+ _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
+ return *this;
+ }
+
+private:
+ template <class _ECharT>
+ static bool __source_is_absolute(_ECharT __first_or_null) {
+ return __is_separator(__first_or_null);
+ }
+
+public:
+ // appends
+ path& operator/=(const path& __p) {
+ if (__p.is_absolute()) {
+ __pn_ = __p.__pn_;
+ return *this;
+ }
+ if (has_filename())
+ __pn_ += preferred_separator;
+ __pn_ += __p.native();
+ return *this;
+ }
+
+ // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
+ // is known at compile time to be "/' since the user almost certainly intended
+ // to append a separator instead of overwriting the path with "/"
+ template <class _Source>
+ _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
+ operator/=(const _Source& __src) {
+ return this->append(__src);
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> append(const _Source& __src) {
+ using _Traits = __is_pathable<_Source>;
+ using _CVT = _PathCVT<_SourceChar<_Source> >;
+ if (__source_is_absolute(_Traits::__first_or_null(__src)))
+ __pn_.clear();
+ else if (has_filename())
+ __pn_ += preferred_separator;
+ _CVT::__append_source(__pn_, __src);
+ return *this;
+ }
+
+ template <class _InputIt>
+ path& append(_InputIt __first, _InputIt __last) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
+ using _CVT = _PathCVT<_ItVal>;
+ if (__first != __last && __source_is_absolute(*__first))
+ __pn_.clear();
+ else if (has_filename())
+ __pn_ += preferred_separator;
+ _CVT::__append_range(__pn_, __first, __last);
+ return *this;
+ }
+
+ // concatenation
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(const path& __x) {
+ __pn_ += __x.__pn_;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(const string_type& __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(__string_view __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(const value_type* __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(value_type __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ template <class _ECharT>
+ typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
+ operator+=(_ECharT __x) {
+ basic_string<_ECharT> __tmp;
+ __tmp += __x;
+ _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
+ return *this;
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> operator+=(const _Source& __x) {
+ return this->concat(__x);
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> concat(const _Source& __x) {
+ _SourceCVT<_Source>::__append_source(__pn_, __x);
+ return *this;
+ }
+
+ template <class _InputIt>
+ path& concat(_InputIt __first, _InputIt __last) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
+ return *this;
+ }
+
+ // modifiers
+ _LIBCPP_INLINE_VISIBILITY
+ void clear() noexcept { __pn_.clear(); }
+
+ path& make_preferred() { return *this; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& remove_filename() {
+ auto __fname = __filename();
+ if (!__fname.empty())
+ __pn_.erase(__fname.data() - __pn_.data());
+ return *this;
+ }
+
+ path& replace_filename(const path& __replacement) {
+ remove_filename();
+ return (*this /= __replacement);
+ }
+
+ path& replace_extension(const path& __replacement = path());
+
+ _LIBCPP_INLINE_VISIBILITY
+ void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
+
+ // private helper to allow reserving memory in the path
+ _LIBCPP_INLINE_VISIBILITY
+ void __reserve(size_t __s) { __pn_.reserve(__s); }
+
+ // native format observers
+ _LIBCPP_INLINE_VISIBILITY
+ const string_type& native() const noexcept { return __pn_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const value_type* c_str() const noexcept { return __pn_.c_str(); }
+
+ _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
+
+ template <class _ECharT, class _Traits = char_traits<_ECharT>,
+ class _Allocator = allocator<_ECharT> >
+ basic_string<_ECharT, _Traits, _Allocator>
+ string(const _Allocator& __a = _Allocator()) const {
+ using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
+ using _Str = basic_string<_ECharT, _Traits, _Allocator>;
+ _Str __s(__a);
+ __s.reserve(__pn_.size());
+ _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
+ return __s;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; }
+ _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const {
+ return string<wchar_t>();
+ }
+ _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; }
+ _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const {
+ return string<char16_t>();
+ }
+ _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const {
+ return string<char32_t>();
+ }
+
+ // generic format observers
+ template <class _ECharT, class _Traits = char_traits<_ECharT>,
+ class _Allocator = allocator<_ECharT> >
+ basic_string<_ECharT, _Traits, _Allocator>
+ generic_string(const _Allocator& __a = _Allocator()) const {
+ return string<_ECharT, _Traits, _Allocator>(__a);
+ }
+
+ std::string generic_string() const { return __pn_; }
+ std::wstring generic_wstring() const { return string<wchar_t>(); }
+ std::string generic_u8string() const { return __pn_; }
+ std::u16string generic_u16string() const { return string<char16_t>(); }
+ std::u32string generic_u32string() const { return string<char32_t>(); }
+
+private:
+ int __compare(__string_view) const;
+ __string_view __root_name() const;
+ __string_view __root_directory() const;
+ __string_view __root_path_raw() const;
+ __string_view __relative_path() const;
+ __string_view __parent_path() const;
+ __string_view __filename() const;
+ __string_view __stem() const;
+ __string_view __extension() const;
+
+public:
+ // compare
+ _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
+ return __compare(__p.__pn_);
+ }
+ _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
+ return __compare(__s);
+ }
+ _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
+ return __compare(__s);
+ }
+ _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
+ return __compare(__s);
+ }
+
+ // decomposition
+ _LIBCPP_INLINE_VISIBILITY path root_name() const {
+ return string_type(__root_name());
+ }
+ _LIBCPP_INLINE_VISIBILITY path root_directory() const {
+ return string_type(__root_directory());
+ }
+ _LIBCPP_INLINE_VISIBILITY path root_path() const {
+ return root_name().append(string_type(__root_directory()));
+ }
+ _LIBCPP_INLINE_VISIBILITY path relative_path() const {
+ return string_type(__relative_path());
+ }
+ _LIBCPP_INLINE_VISIBILITY path parent_path() const {
+ return string_type(__parent_path());
+ }
+ _LIBCPP_INLINE_VISIBILITY path filename() const {
+ return string_type(__filename());
+ }
+ _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
+ _LIBCPP_INLINE_VISIBILITY path extension() const {
+ return string_type(__extension());
+ }
+
+ // query
+ _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
+ empty() const noexcept {
+ return __pn_.empty();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
+ return !__root_name().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
+ return !__root_directory().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
+ return !__root_path_raw().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
+ return !__relative_path().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
+ return !__parent_path().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
+ return !__filename().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
+ _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
+ return !__extension().empty();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
+ return has_root_directory();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
+
+ // relative paths
+ path lexically_normal() const;
+ path lexically_relative(const path& __base) const;
+
+ _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
+ path __result = this->lexically_relative(__base);
+ if (__result.native().empty())
+ return *this;
+ return __result;
+ }
+
+ // iterators
+ class _LIBCPP_TYPE_VIS iterator;
+ typedef iterator const_iterator;
+
+ iterator begin() const;
+ iterator end() const;
+
+ template <class _CharT, class _Traits>
+ _LIBCPP_INLINE_VISIBILITY friend
+ typename enable_if<is_same<_CharT, char>::value &&
+ is_same<_Traits, char_traits<char> >::value,
+ basic_ostream<_CharT, _Traits>&>::type
+ operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
+ __os << std::__quoted(__p.native());
+ return __os;
+ }
+
+ template <class _CharT, class _Traits>
+ _LIBCPP_INLINE_VISIBILITY friend
+ typename enable_if<!is_same<_CharT, char>::value ||
+ !is_same<_Traits, char_traits<char> >::value,
+ basic_ostream<_CharT, _Traits>&>::type
+ operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
+ __os << std::__quoted(__p.string<_CharT, _Traits>());
+ return __os;
+ }
+
+ template <class _CharT, class _Traits>
+ _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
+ operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
+ basic_string<_CharT, _Traits> __tmp;
+ __is >> __quoted(__tmp);
+ __p = __tmp;
+ return __is;
+ }
+
+ friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) == 0;
+ }
+ friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) != 0;
+ }
+ friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) < 0;
+ }
+ friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) <= 0;
+ }
+ friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) > 0;
+ }
+ friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) >= 0;
+ }
+
+ friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
+ const path& __rhs) {
+ path __result(__lhs);
+ __result /= __rhs;
+ return __result;
+ }
+private:
+ inline _LIBCPP_INLINE_VISIBILITY path&
+ __assign_view(__string_view const& __s) noexcept {
+ __pn_ = string_type(__s);
+ return *this;
+ }
+ string_type __pn_;
+};
+
+inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
+ __lhs.swap(__rhs);
+}
+
+_LIBCPP_FUNC_VIS
+size_t hash_value(const path& __p) noexcept;
+
+template <class _Source>
+_LIBCPP_INLINE_VISIBILITY
+ typename enable_if<__is_pathable<_Source>::value, path>::type
+ u8path(const _Source& __s) {
+ static_assert(
+ is_same<typename __is_pathable<_Source>::__char_type, char>::value,
+ "u8path(Source const&) requires Source have a character type of type "
+ "'char'");
+ return path(__s);
+}
+
+template <class _InputIt>
+_LIBCPP_INLINE_VISIBILITY
+ typename enable_if<__is_pathable<_InputIt>::value, path>::type
+ u8path(_InputIt __f, _InputIt __l) {
+ static_assert(
+ is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
+ "u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
+ return path(__f, __l);
+}
+
+class _LIBCPP_TYPE_VIS path::iterator {
+public:
+ enum _ParserState : unsigned char {
+ _Singular,
+ _BeforeBegin,
+ _InRootName,
+ _InRootDir,
+ _InFilenames,
+ _InTrailingSep,
+ _AtEnd
+ };
+
+public:
+ typedef bidirectional_iterator_tag iterator_category;
+
+ typedef path value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef const path* pointer;
+ typedef const path& reference;
+
+ typedef void
+ __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
+
+public:
+ _LIBCPP_INLINE_VISIBILITY
+ iterator()
+ : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
+ __state_(_Singular) {}
+
+ iterator(const iterator&) = default;
+ ~iterator() = default;
+
+ iterator& operator=(const iterator&) = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ reference operator*() const { return __stashed_elem_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ pointer operator->() const { return &__stashed_elem_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator& operator++() {
+ _LIBCPP_ASSERT(__state_ != _Singular,
+ "attempting to increment a singular iterator");
+ _LIBCPP_ASSERT(__state_ != _AtEnd,
+ "attempting to increment the end iterator");
+ return __increment();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator operator++(int) {
+ iterator __it(*this);
+ this->operator++();
+ return __it;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator& operator--() {
+ _LIBCPP_ASSERT(__state_ != _Singular,
+ "attempting to decrement a singular iterator");
+ _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
+ "attempting to decrement the begin iterator");
+ return __decrement();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator operator--(int) {
+ iterator __it(*this);
+ this->operator--();
+ return __it;
+ }
+
+private:
+ friend class path;
+
+ inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
+ const iterator&);
+
+ iterator& __increment();
+ iterator& __decrement();
+
+ path __stashed_elem_;
+ const path* __path_ptr_;
+ path::__string_view __entry_;
+ _ParserState __state_;
+};
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
+ const path::iterator& __rhs) {
+ return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
+ __lhs.__entry_.data() == __rhs.__entry_.data();
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
+ const path::iterator& __rhs) {
+ return !(__lhs == __rhs);
+}
+
+class _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
+public:
+ _LIBCPP_INLINE_VISIBILITY
+ filesystem_error(const string& __what, error_code __ec)
+ : system_error(__ec, __what),
+ __storage_(make_shared<_Storage>(path(), path())) {
+ __create_what(0);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ filesystem_error(const string& __what, const path& __p1, error_code __ec)
+ : system_error(__ec, __what),
+ __storage_(make_shared<_Storage>(__p1, path())) {
+ __create_what(1);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ filesystem_error(const string& __what, const path& __p1, const path& __p2,
+ error_code __ec)
+ : system_error(__ec, __what),
+ __storage_(make_shared<_Storage>(__p1, __p2)) {
+ __create_what(2);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const path& path1() const noexcept { return __storage_->__p1_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const path& path2() const noexcept { return __storage_->__p2_; }
+
+ ~filesystem_error() override; // key function
+
+ _LIBCPP_INLINE_VISIBILITY
+ const char* what() const noexcept override {
+ return __storage_->__what_.c_str();
+ }
+
+ _LIBCPP_FUNC_VIS
+ void __create_what(int __num_paths);
+
+private:
+ struct _Storage {
+ _LIBCPP_INLINE_VISIBILITY
+ _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
+
+ path __p1_;
+ path __p2_;
+ string __what_;
+ };
+ shared_ptr<_Storage> __storage_;
+};
+
+template <class... _Args>
+_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ void
+ __throw_filesystem_error(_Args&&... __args) {
+ throw filesystem_error(std::forward<_Args>(__args)...);
+}
+#else
+ void
+ __throw_filesystem_error(_Args&&...) {
+ _VSTD::abort();
+}
+#endif
+
+// operational functions
+
+_LIBCPP_FUNC_VIS
+path __absolute(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+path __canonical(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __copy(const path& __from, const path& __to, copy_options __opt,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __copy_file(const path& __from, const path& __to, copy_options __opt,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __create_directories(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __create_directory(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __create_directory(const path& p, const path& attributes,
+ error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __create_directory_symlink(const path& __to, const path& __new_symlink,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __create_hard_link(const path& __to, const path& __new_hard_link,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __create_symlink(const path& __to, const path& __new_symlink,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+path __current_path(error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __current_path(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+uintmax_t __file_size(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __fs_is_empty(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __last_write_time(const path& p, file_time_type new_time,
+ error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __permissions(const path&, perms, perm_options, error_code* = nullptr);
+_LIBCPP_FUNC_VIS
+path __read_symlink(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __remove(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __rename(const path& from, const path& to, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+space_info __space(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+file_status __status(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+file_status __symlink_status(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+path __system_complete(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+path __temp_directory_path(error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
+
+inline _LIBCPP_INLINE_VISIBILITY path current_path() {
+ return __current_path();
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
+ return __current_path(&__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
+ __current_path(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
+ error_code& __ec) noexcept {
+ __current_path(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
+ return __absolute(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
+ error_code& __ec) {
+ return __absolute(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
+ return __canonical(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
+ error_code& __ec) {
+ return __canonical(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
+ const path& __to) {
+ __copy(__from, __to, copy_options::none);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
+ error_code& __ec) {
+ __copy(__from, __to, copy_options::none, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
+ copy_options __opt) {
+ __copy(__from, __to, __opt);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
+ copy_options __opt,
+ error_code& __ec) {
+ __copy(__from, __to, __opt, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
+ const path& __to) {
+ return __copy_file(__from, __to, copy_options::none);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+copy_file(const path& __from, const path& __to, error_code& __ec) {
+ return __copy_file(__from, __to, copy_options::none, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+copy_file(const path& __from, const path& __to, copy_options __opt) {
+ return __copy_file(__from, __to, __opt);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
+ const path& __to,
+ copy_options __opt,
+ error_code& __ec) {
+ return __copy_file(__from, __to, __opt, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
+ const path& __new) {
+ __copy_symlink(__existing, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
+ __copy_symlink(__ext, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
+ return __create_directories(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
+ error_code& __ec) {
+ return __create_directories(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
+ return __create_directory(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+create_directory(const path& __p, error_code& __ec) noexcept {
+ return __create_directory(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
+ const path& __attrs) {
+ return __create_directory(__p, __attrs);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+create_directory(const path& __p, const path& __attrs,
+ error_code& __ec) noexcept {
+ return __create_directory(__p, __attrs, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_directory_symlink(const path& __to, const path& __new) {
+ __create_directory_symlink(__to, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_directory_symlink(const path& __to, const path& __new,
+ error_code& __ec) noexcept {
+ __create_directory_symlink(__to, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
+ const path& __new) {
+ __create_hard_link(__to, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_hard_link(const path& __to, const path& __new,
+ error_code& __ec) noexcept {
+ __create_hard_link(__to, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
+ const path& __new) {
+ __create_symlink(__to, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
+ return __create_symlink(__to, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
+ return __s.type() != file_type::none;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
+ return status_known(__s) && __s.type() != file_type::not_found;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
+ return exists(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
+ error_code& __ec) noexcept {
+ auto __s = __status(__p, &__ec);
+ if (status_known(__s))
+ __ec.clear();
+ return exists(__s);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
+ const path& __p2) {
+ return __equivalent(__p1, __p2);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
+ return __equivalent(__p1, __p2, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
+ return __file_size(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t
+file_size(const path& __p, error_code& __ec) noexcept {
+ return __file_size(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
+ return __hard_link_count(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t
+hard_link_count(const path& __p, error_code& __ec) noexcept {
+ return __hard_link_count(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
+ return __s.type() == file_type::block;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
+ return is_block_file(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
+ error_code& __ec) noexcept {
+ return is_block_file(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_character_file(file_status __s) noexcept {
+ return __s.type() == file_type::character;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
+ return is_character_file(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_character_file(const path& __p, error_code& __ec) noexcept {
+ return is_character_file(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
+ return __s.type() == file_type::directory;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
+ return is_directory(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
+ error_code& __ec) noexcept {
+ return is_directory(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
+ return __fs_is_empty(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
+ error_code& __ec) {
+ return __fs_is_empty(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
+ return __s.type() == file_type::fifo;
+}
+inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
+ return is_fifo(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
+ error_code& __ec) noexcept {
+ return is_fifo(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_regular_file(file_status __s) noexcept {
+ return __s.type() == file_type::regular;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
+ return is_regular_file(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_regular_file(const path& __p, error_code& __ec) noexcept {
+ return is_regular_file(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
+ return __s.type() == file_type::socket;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
+ return is_socket(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
+ error_code& __ec) noexcept {
+ return is_socket(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
+ return __s.type() == file_type::symlink;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
+ return is_symlink(__symlink_status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
+ error_code& __ec) noexcept {
+ return is_symlink(__symlink_status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
+ return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
+ !is_symlink(__s);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
+ return is_other(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
+ error_code& __ec) noexcept {
+ return is_other(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_time_type
+last_write_time(const path& __p) {
+ return __last_write_time(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_time_type
+last_write_time(const path& __p, error_code& __ec) noexcept {
+ return __last_write_time(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
+ file_time_type __t) {
+ __last_write_time(__p, __t);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+last_write_time(const path& __p, file_time_type __t,
+ error_code& __ec) noexcept {
+ __last_write_time(__p, __t, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+permissions(const path& __p, perms __prms,
+ perm_options __opts = perm_options::replace) {
+ __permissions(__p, __prms, __opts);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
+ error_code& __ec) noexcept {
+ __permissions(__p, __prms, perm_options::replace, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
+ perm_options __opts,
+ error_code& __ec) {
+ __permissions(__p, __prms, __opts, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
+ const path& __base,
+ error_code& __ec) {
+ path __tmp = __weakly_canonical(__p, &__ec);
+ if (__ec)
+ return {};
+ path __tmp_base = __weakly_canonical(__base, &__ec);
+ if (__ec)
+ return {};
+ return __tmp.lexically_proximate(__tmp_base);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
+ error_code& __ec) {
+ return proximate(__p, current_path(), __ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path
+proximate(const path& __p, const path& __base = current_path()) {
+ return __weakly_canonical(__p).lexically_proximate(
+ __weakly_canonical(__base));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
+ return __read_symlink(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
+ error_code& __ec) {
+ return __read_symlink(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
+ const path& __base,
+ error_code& __ec) {
+ path __tmp = __weakly_canonical(__p, &__ec);
+ if (__ec)
+ return path();
+ path __tmpbase = __weakly_canonical(__base, &__ec);
+ if (__ec)
+ return path();
+ return __tmp.lexically_relative(__tmpbase);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
+ error_code& __ec) {
+ return relative(__p, current_path(), __ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path
+relative(const path& __p, const path& __base = current_path()) {
+ return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
+ return __remove(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
+ error_code& __ec) noexcept {
+ return __remove(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
+ return __remove_all(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
+ error_code& __ec) {
+ return __remove_all(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
+ const path& __to) {
+ return __rename(__from, __to);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+rename(const path& __from, const path& __to, error_code& __ec) noexcept {
+ return __rename(__from, __to, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
+ uintmax_t __ns) {
+ return __resize_file(__p, __ns);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
+ return __resize_file(__p, __ns, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
+ return __space(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
+ error_code& __ec) noexcept {
+ return __space(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
+ return __status(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
+ error_code& __ec) noexcept {
+ return __status(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
+ return __symlink_status(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status
+symlink_status(const path& __p, error_code& __ec) noexcept {
+ return __symlink_status(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
+ return __temp_directory_path();
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
+ return __temp_directory_path(&__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
+ return __weakly_canonical(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
+ error_code& __ec) {
+ return __weakly_canonical(__p, &__ec);
+}
+
+class directory_iterator;
+class recursive_directory_iterator;
+class __dir_stream;
+
+class directory_entry {
+ typedef _VSTD_FS::path _Path;
+
+public:
+ // constructors and destructors
+ directory_entry() noexcept = default;
+ directory_entry(directory_entry const&) = default;
+ directory_entry(directory_entry&&) noexcept = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ explicit directory_entry(_Path const& __p) : __p_(__p) {
+ error_code __ec;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
+ __refresh(&__ec);
+ }
+
+ ~directory_entry() {}
+
+ directory_entry& operator=(directory_entry const&) = default;
+ directory_entry& operator=(directory_entry&&) noexcept = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ void assign(_Path const& __p) {
+ __p_ = __p;
+ error_code __ec;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void assign(_Path const& __p, error_code& __ec) {
+ __p_ = __p;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void replace_filename(_Path const& __p) {
+ __p_.replace_filename(__p);
+ error_code __ec;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void replace_filename(_Path const& __p, error_code& __ec) {
+ __p_ = __p_.parent_path() / __p;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void refresh() { __refresh(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ _Path const& path() const noexcept { return __p_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ operator const _Path&() const noexcept { return __p_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool exists(error_code& __ec) const noexcept {
+ return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_block_file() const { return __get_ft() == file_type::block; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_block_file(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::block;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_character_file() const { return __get_ft() == file_type::character; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_character_file(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::character;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_directory() const { return __get_ft() == file_type::directory; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_directory(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::directory;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_fifo() const { return __get_ft() == file_type::fifo; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_fifo(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::fifo;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_other(error_code& __ec) const noexcept {
+ return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_regular_file() const { return __get_ft() == file_type::regular; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_regular_file(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::regular;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_socket() const { return __get_ft() == file_type::socket; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_socket(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::socket;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_symlink(error_code& __ec) const noexcept {
+ return __get_sym_ft(&__ec) == file_type::symlink;
+ }
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t file_size() const { return __get_size(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t file_size(error_code& __ec) const noexcept {
+ return __get_size(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t hard_link_count() const { return __get_nlink(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t hard_link_count(error_code& __ec) const noexcept {
+ return __get_nlink(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_time_type last_write_time() const { return __get_write_time(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_time_type last_write_time(error_code& __ec) const noexcept {
+ return __get_write_time(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status status() const { return __get_status(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status status(error_code& __ec) const noexcept {
+ return __get_status(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status symlink_status() const { return __get_symlink_status(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status symlink_status(error_code& __ec) const noexcept {
+ return __get_symlink_status(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator<(directory_entry const& __rhs) const noexcept {
+ return __p_ < __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator==(directory_entry const& __rhs) const noexcept {
+ return __p_ == __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator!=(directory_entry const& __rhs) const noexcept {
+ return __p_ != __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator<=(directory_entry const& __rhs) const noexcept {
+ return __p_ <= __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator>(directory_entry const& __rhs) const noexcept {
+ return __p_ > __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator>=(directory_entry const& __rhs) const noexcept {
+ return __p_ >= __rhs.__p_;
+ }
+
+private:
+ friend class directory_iterator;
+ friend class recursive_directory_iterator;
+ friend class __dir_stream;
+
+ enum _CacheType : unsigned char {
+ _Empty,
+ _IterSymlink,
+ _IterNonSymlink,
+ _RefreshSymlink,
+ _RefreshSymlinkUnresolved,
+ _RefreshNonSymlink
+ };
+
+ struct __cached_data {
+ uintmax_t __size_;
+ uintmax_t __nlink_;
+ file_time_type __write_time_;
+ perms __sym_perms_;
+ perms __non_sym_perms_;
+ file_type __type_;
+ _CacheType __cache_type_;
+
+ _LIBCPP_INLINE_VISIBILITY
+ __cached_data() noexcept { __reset(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __reset() {
+ __cache_type_ = _Empty;
+ __type_ = file_type::none;
+ __sym_perms_ = __non_sym_perms_ = perms::unknown;
+ __size_ = __nlink_ = uintmax_t(-1);
+ __write_time_ = file_time_type::min();
+ }
+ };
+
+ _LIBCPP_INLINE_VISIBILITY
+ static __cached_data __create_iter_result(file_type __ft) {
+ __cached_data __data;
+ __data.__type_ = __ft;
+ __data.__cache_type_ = [&]() {
+ switch (__ft) {
+ case file_type::none:
+ return _Empty;
+ case file_type::symlink:
+ return _IterSymlink;
+ default:
+ return _IterNonSymlink;
+ }
+ }();
+ return __data;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
+ __p_ = std::move(__p);
+ __data_ = __dt;
+ }
+
+ _LIBCPP_FUNC_VIS
+ error_code __do_refresh() noexcept;
+
+ _LIBCPP_INLINE_VISIBILITY
+ static bool __is_dne_error(error_code const& __ec) {
+ if (!__ec)
+ return true;
+ switch (static_cast<errc>(__ec.value())) {
+ case errc::no_such_file_or_directory:
+ case errc::not_a_directory:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __handle_error(const char* __msg, error_code* __dest_ec,
+ error_code const& __ec, bool __allow_dne = false) const {
+ if (__dest_ec) {
+ *__dest_ec = __ec;
+ return;
+ }
+ if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
+ __throw_filesystem_error(__msg, __p_, __ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __refresh(error_code* __ec = nullptr) {
+ __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
+ /*allow_dne*/ true);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_type __get_sym_ft(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ return __symlink_status(__p_, __ec).type();
+ case _IterSymlink:
+ case _RefreshSymlink:
+ case _RefreshSymlinkUnresolved:
+ if (__ec)
+ __ec->clear();
+ return file_type::symlink;
+ case _IterNonSymlink:
+ case _RefreshNonSymlink:
+ file_status __st(__data_.__type_);
+ if (__ec && !_VSTD_FS::exists(__st))
+ *__ec = make_error_code(errc::no_such_file_or_directory);
+ else if (__ec)
+ __ec->clear();
+ return __data_.__type_;
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_type __get_ft(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return __status(__p_, __ec).type();
+ case _IterNonSymlink:
+ case _RefreshNonSymlink:
+ case _RefreshSymlink: {
+ file_status __st(__data_.__type_);
+ if (__ec && !_VSTD_FS::exists(__st))
+ *__ec = make_error_code(errc::no_such_file_or_directory);
+ else if (__ec)
+ __ec->clear();
+ return __data_.__type_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status __get_status(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return __status(__p_, __ec);
+ case _RefreshNonSymlink:
+ case _RefreshSymlink:
+ return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status __get_symlink_status(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ return __symlink_status(__p_, __ec);
+ case _RefreshNonSymlink:
+ return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
+ case _RefreshSymlink:
+ case _RefreshSymlinkUnresolved:
+ return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t __get_size(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return _VSTD_FS::__file_size(__p_, __ec);
+ case _RefreshSymlink:
+ case _RefreshNonSymlink: {
+ error_code __m_ec;
+ file_status __st(__get_ft(&__m_ec));
+ __handle_error("in directory_entry::file_size", __ec, __m_ec);
+ if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
+ errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
+ : errc::not_supported;
+ __handle_error("in directory_entry::file_size", __ec,
+ make_error_code(__err_kind));
+ }
+ return __data_.__size_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t __get_nlink(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return _VSTD_FS::__hard_link_count(__p_, __ec);
+ case _RefreshSymlink:
+ case _RefreshNonSymlink: {
+ error_code __m_ec;
+ (void)__get_ft(&__m_ec);
+ __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
+ return __data_.__nlink_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_time_type __get_write_time(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return _VSTD_FS::__last_write_time(__p_, __ec);
+ case _RefreshSymlink:
+ case _RefreshNonSymlink: {
+ error_code __m_ec;
+ file_status __st(__get_ft(&__m_ec));
+ __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
+ if (_VSTD_FS::exists(__st) &&
+ __data_.__write_time_ == file_time_type::min())
+ __handle_error("in directory_entry::last_write_time", __ec,
+ make_error_code(errc::value_too_large));
+ return __data_.__write_time_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+private:
+ _Path __p_;
+ __cached_data __data_;
+};
+
+class __dir_element_proxy {
+public:
+ inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
+ return _VSTD::move(__elem_);
+ }
+
+private:
+ friend class directory_iterator;
+ friend class recursive_directory_iterator;
+ explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
+ __dir_element_proxy(__dir_element_proxy&& __o)
+ : __elem_(_VSTD::move(__o.__elem_)) {}
+ directory_entry __elem_;
+};
+
+class directory_iterator {
+public:
+ typedef directory_entry value_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type const* pointer;
+ typedef value_type const& reference;
+ typedef input_iterator_tag iterator_category;
+
+public:
+ //ctor & dtor
+ directory_iterator() noexcept {}
+
+ explicit directory_iterator(const path& __p)
+ : directory_iterator(__p, nullptr) {}
+
+ directory_iterator(const path& __p, directory_options __opts)
+ : directory_iterator(__p, nullptr, __opts) {}
+
+ directory_iterator(const path& __p, error_code& __ec)
+ : directory_iterator(__p, &__ec) {}
+
+ directory_iterator(const path& __p, directory_options __opts,
+ error_code& __ec)
+ : directory_iterator(__p, &__ec, __opts) {}
+
+ directory_iterator(const directory_iterator&) = default;
+ directory_iterator(directory_iterator&&) = default;
+ directory_iterator& operator=(const directory_iterator&) = default;
+
+ directory_iterator& operator=(directory_iterator&& __o) noexcept {
+ // non-default implementation provided to support self-move assign.
+ if (this != &__o) {
+ __imp_ = _VSTD::move(__o.__imp_);
+ }
+ return *this;
+ }
+
+ ~directory_iterator() = default;
+
+ const directory_entry& operator*() const {
+ _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
+ return __dereference();
+ }
+
+ const directory_entry* operator->() const { return &**this; }
+
+ directory_iterator& operator++() { return __increment(); }
+
+ __dir_element_proxy operator++(int) {
+ __dir_element_proxy __p(**this);
+ __increment();
+ return __p;
+ }
+
+ directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
+
+private:
+ inline _LIBCPP_INLINE_VISIBILITY friend bool
+ operator==(const directory_iterator& __lhs,
+ const directory_iterator& __rhs) noexcept;
+
+ // construct the dir_stream
+ _LIBCPP_FUNC_VIS
+ directory_iterator(const path&, error_code*,
+ directory_options = directory_options::none);
+
+ _LIBCPP_FUNC_VIS
+ directory_iterator& __increment(error_code* __ec = nullptr);
+
+ _LIBCPP_FUNC_VIS
+ const directory_entry& __dereference() const;
+
+private:
+ shared_ptr<__dir_stream> __imp_;
+};
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+operator==(const directory_iterator& __lhs,
+ const directory_iterator& __rhs) noexcept {
+ return __lhs.__imp_ == __rhs.__imp_;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+operator!=(const directory_iterator& __lhs,
+ const directory_iterator& __rhs) noexcept {
+ return !(__lhs == __rhs);
+}
+
+// enable directory_iterator range-based for statements
+inline _LIBCPP_INLINE_VISIBILITY directory_iterator
+begin(directory_iterator __iter) noexcept {
+ return __iter;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY directory_iterator
+end(const directory_iterator&) noexcept {
+ return directory_iterator();
+}
+
+class recursive_directory_iterator {
+public:
+ using value_type = directory_entry;
+ using difference_type = std::ptrdiff_t;
+ using pointer = directory_entry const*;
+ using reference = directory_entry const&;
+ using iterator_category = std::input_iterator_tag;
+
+public:
+ // constructors and destructor
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator() noexcept : __rec_(false) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ explicit recursive_directory_iterator(
+ const path& __p, directory_options __xoptions = directory_options::none)
+ : recursive_directory_iterator(__p, __xoptions, nullptr) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator(const path& __p, directory_options __xoptions,
+ error_code& __ec)
+ : recursive_directory_iterator(__p, __xoptions, &__ec) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator(const path& __p, error_code& __ec)
+ : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
+
+ recursive_directory_iterator(const recursive_directory_iterator&) = default;
+ recursive_directory_iterator(recursive_directory_iterator&&) = default;
+
+ recursive_directory_iterator&
+ operator=(const recursive_directory_iterator&) = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator&
+ operator=(recursive_directory_iterator&& __o) noexcept {
+ // non-default implementation provided to support self-move assign.
+ if (this != &__o) {
+ __imp_ = _VSTD::move(__o.__imp_);
+ __rec_ = __o.__rec_;
+ }
+ return *this;
+ }
+
+ ~recursive_directory_iterator() = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ const directory_entry& operator*() const { return __dereference(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const directory_entry* operator->() const { return &__dereference(); }
+
+ recursive_directory_iterator& operator++() { return __increment(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ __dir_element_proxy operator++(int) {
+ __dir_element_proxy __p(**this);
+ __increment();
+ return __p;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator& increment(error_code& __ec) {
+ return __increment(&__ec);
+ }
+
+ _LIBCPP_FUNC_VIS directory_options options() const;
+ _LIBCPP_FUNC_VIS int depth() const;
+
+ _LIBCPP_INLINE_VISIBILITY
+ void pop() { __pop(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void pop(error_code& __ec) { __pop(&__ec); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool recursion_pending() const { return __rec_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void disable_recursion_pending() { __rec_ = false; }
+
+private:
+ recursive_directory_iterator(const path& __p, directory_options __opt,
+ error_code* __ec);
+
+ _LIBCPP_FUNC_VIS
+ const directory_entry& __dereference() const;
+
+ _LIBCPP_FUNC_VIS
+ bool __try_recursion(error_code* __ec);
+
+ _LIBCPP_FUNC_VIS
+ void __advance(error_code* __ec = nullptr);
+
+ _LIBCPP_FUNC_VIS
+ recursive_directory_iterator& __increment(error_code* __ec = nullptr);
+
+ _LIBCPP_FUNC_VIS
+ void __pop(error_code* __ec = nullptr);
+
+ inline _LIBCPP_INLINE_VISIBILITY friend bool
+ operator==(const recursive_directory_iterator&,
+ const recursive_directory_iterator&) noexcept;
+
+ struct __shared_imp;
+ shared_ptr<__shared_imp> __imp_;
+ bool __rec_;
+}; // class recursive_directory_iterator
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+operator==(const recursive_directory_iterator& __lhs,
+ const recursive_directory_iterator& __rhs) noexcept {
+ return __lhs.__imp_ == __rhs.__imp_;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline bool operator!=(const recursive_directory_iterator& __lhs,
+ const recursive_directory_iterator& __rhs) noexcept {
+ return !(__lhs == __rhs);
+}
+// enable recursive_directory_iterator range-based for statements
+inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
+begin(recursive_directory_iterator __iter) noexcept {
+ return __iter;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
+end(const recursive_directory_iterator&) noexcept {
+ return recursive_directory_iterator();
+}
+
+} // namespace android::hardware::automotive::filesystem
+#ifdef _LIBAUTO_UNDEF_VSTD
+#undef _VSTD
+#undef _LIBAUTO_UNDEF_VSTD
+#endif
+
+#ifndef _LIBAUTO_UNDEF_VSTD_FS
+#pragma pop_macro("_VSTD_FS")
+#else
+#undef _VSTD
+#undef _LIBAUTO_UNDEF_VSTD_FS
+#endif
+
+#endif // !_LIBCPP_CXX03_LANG
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBAUTO_FILESYSTEM
diff --git a/automotive/can/1.0/default/libc++fs/src b/automotive/can/1.0/default/libc++fs/src
deleted file mode 120000
index 7abb4ba..0000000
--- a/automotive/can/1.0/default/libc++fs/src
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../../external/libcxx/src/
\ No newline at end of file
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp b/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp
new file mode 100644
index 0000000..624538b
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp
@@ -0,0 +1,397 @@
+//===------------------ directory_iterator.cpp ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/* clang-format off */
+#include "automotive/filesystem"
+#include <__config>
+#if defined(_LIBCPP_WIN32API)
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#else
+#include <dirent.h>
+#endif
+#include <errno.h>
+
+#include "filesystem_common.h"
+
+namespace android::hardware::automotive::filesystem {
+
+namespace detail {
+namespace {
+
+#if !defined(_LIBCPP_WIN32API)
+template <class DirEntT, class = decltype(DirEntT::d_type)>
+static file_type get_file_type(DirEntT* ent, int) {
+ switch (ent->d_type) {
+ case DT_BLK:
+ return file_type::block;
+ case DT_CHR:
+ return file_type::character;
+ case DT_DIR:
+ return file_type::directory;
+ case DT_FIFO:
+ return file_type::fifo;
+ case DT_LNK:
+ return file_type::symlink;
+ case DT_REG:
+ return file_type::regular;
+ case DT_SOCK:
+ return file_type::socket;
+ // Unlike in lstat, hitting "unknown" here simply means that the underlying
+ // filesystem doesn't support d_type. Report is as 'none' so we correctly
+ // set the cache to empty.
+ case DT_UNKNOWN:
+ break;
+ }
+ return file_type::none;
+}
+
+template <class DirEntT>
+static file_type get_file_type(DirEntT* ent, long) {
+ return file_type::none;
+}
+
+static pair<string_view, file_type> posix_readdir(DIR* dir_stream,
+ error_code& ec) {
+ struct dirent* dir_entry_ptr = nullptr;
+ errno = 0; // zero errno in order to detect errors
+ ec.clear();
+ if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
+ if (errno)
+ ec = capture_errno();
+ return {};
+ } else {
+ return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)};
+ }
+}
+#else
+
+static file_type get_file_type(const WIN32_FIND_DATA& data) {
+ //auto attrs = data.dwFileAttributes;
+ // FIXME(EricWF)
+ return file_type::unknown;
+}
+static uintmax_t get_file_size(const WIN32_FIND_DATA& data) {
+ return (data.nFileSizeHight * (MAXDWORD + 1)) + data.nFileSizeLow;
+}
+static file_time_type get_write_time(const WIN32_FIND_DATA& data) {
+ ULARGE_INTEGER tmp;
+ FILETIME& time = data.ftLastWriteTime;
+ tmp.u.LowPart = time.dwLowDateTime;
+ tmp.u.HighPart = time.dwHighDateTime;
+ return file_time_type(file_time_type::duration(time.QuadPart));
+}
+
+#endif
+
+} // namespace
+} // namespace detail
+
+using detail::ErrorHandler;
+
+#if defined(_LIBCPP_WIN32API)
+class __dir_stream {
+public:
+ __dir_stream() = delete;
+ __dir_stream& operator=(const __dir_stream&) = delete;
+
+ __dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_),
+ __root_(move(__ds.__root_)),
+ __entry_(move(__ds.__entry_)) {
+ __ds.__stream_ = INVALID_HANDLE_VALUE;
+ }
+
+ __dir_stream(const path& root, directory_options opts, error_code& ec)
+ : __stream_(INVALID_HANDLE_VALUE), __root_(root) {
+ __stream_ = ::FindFirstFileEx(root.c_str(), &__data_);
+ if (__stream_ == INVALID_HANDLE_VALUE) {
+ ec = error_code(::GetLastError(), generic_category());
+ const bool ignore_permission_denied =
+ bool(opts & directory_options::skip_permission_denied);
+ if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED)
+ ec.clear();
+ return;
+ }
+ }
+
+ ~__dir_stream() noexcept {
+ if (__stream_ == INVALID_HANDLE_VALUE)
+ return;
+ close();
+ }
+
+ bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; }
+
+ bool advance(error_code& ec) {
+ while (::FindNextFile(__stream_, &__data_)) {
+ if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, ".."))
+ continue;
+ // FIXME: Cache more of this
+ //directory_entry::__cached_data cdata;
+ //cdata.__type_ = get_file_type(__data_);
+ //cdata.__size_ = get_file_size(__data_);
+ //cdata.__write_time_ = get_write_time(__data_);
+ __entry_.__assign_iter_entry(
+ __root_ / __data_.cFileName,
+ directory_entry::__create_iter_result(get_file_type(__data)));
+ return true;
+ }
+ ec = error_code(::GetLastError(), generic_category());
+ close();
+ return false;
+ }
+
+private:
+ error_code close() noexcept {
+ error_code ec;
+ if (!::FindClose(__stream_))
+ ec = error_code(::GetLastError(), generic_category());
+ __stream_ = INVALID_HANDLE_VALUE;
+ return ec;
+ }
+
+ HANDLE __stream_{INVALID_HANDLE_VALUE};
+ WIN32_FIND_DATA __data_;
+
+public:
+ path __root_;
+ directory_entry __entry_;
+};
+#else
+class __dir_stream {
+public:
+ __dir_stream() = delete;
+ __dir_stream& operator=(const __dir_stream&) = delete;
+
+ __dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_),
+ __root_(move(other.__root_)),
+ __entry_(move(other.__entry_)) {
+ other.__stream_ = nullptr;
+ }
+
+ __dir_stream(const path& root, directory_options opts, error_code& ec)
+ : __stream_(nullptr), __root_(root) {
+ if ((__stream_ = ::opendir(root.c_str())) == nullptr) {
+ ec = detail::capture_errno();
+ const bool allow_eacess =
+ bool(opts & directory_options::skip_permission_denied);
+ if (allow_eacess && ec.value() == EACCES)
+ ec.clear();
+ return;
+ }
+ advance(ec);
+ }
+
+ ~__dir_stream() noexcept {
+ if (__stream_)
+ close();
+ }
+
+ bool good() const noexcept { return __stream_ != nullptr; }
+
+ bool advance(error_code& ec) {
+ while (true) {
+ auto str_type_pair = detail::posix_readdir(__stream_, ec);
+ auto& str = str_type_pair.first;
+ if (str == "." || str == "..") {
+ continue;
+ } else if (ec || str.empty()) {
+ close();
+ return false;
+ } else {
+ __entry_.__assign_iter_entry(
+ __root_ / str,
+ directory_entry::__create_iter_result(str_type_pair.second));
+ return true;
+ }
+ }
+ }
+
+private:
+ error_code close() noexcept {
+ error_code m_ec;
+ if (::closedir(__stream_) == -1)
+ m_ec = detail::capture_errno();
+ __stream_ = nullptr;
+ return m_ec;
+ }
+
+ DIR* __stream_{nullptr};
+
+public:
+ path __root_;
+ directory_entry __entry_;
+};
+#endif
+
+// directory_iterator
+
+directory_iterator::directory_iterator(const path& p, error_code* ec,
+ directory_options opts) {
+ ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p);
+
+ error_code m_ec;
+ __imp_ = make_shared<__dir_stream>(p, opts, m_ec);
+ if (ec)
+ *ec = m_ec;
+ if (!__imp_->good()) {
+ __imp_.reset();
+ if (m_ec)
+ err.report(m_ec);
+ }
+}
+
+directory_iterator& directory_iterator::__increment(error_code* ec) {
+ _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator");
+ ErrorHandler<void> err("directory_iterator::operator++()", ec);
+
+ error_code m_ec;
+ if (!__imp_->advance(m_ec)) {
+ path root = move(__imp_->__root_);
+ __imp_.reset();
+ if (m_ec)
+ err.report(m_ec, "at root \"%s\"", root);
+ }
+ return *this;
+}
+
+directory_entry const& directory_iterator::__dereference() const {
+ _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator");
+ return __imp_->__entry_;
+}
+
+// recursive_directory_iterator
+
+struct recursive_directory_iterator::__shared_imp {
+ stack<__dir_stream> __stack_;
+ directory_options __options_;
+};
+
+recursive_directory_iterator::recursive_directory_iterator(
+ const path& p, directory_options opt, error_code* ec)
+ : __imp_(nullptr), __rec_(true) {
+ ErrorHandler<void> err("recursive_directory_iterator", ec, &p);
+
+ error_code m_ec;
+ __dir_stream new_s(p, opt, m_ec);
+ if (m_ec)
+ err.report(m_ec);
+ if (m_ec || !new_s.good())
+ return;
+
+ __imp_ = make_shared<__shared_imp>();
+ __imp_->__options_ = opt;
+ __imp_->__stack_.push(move(new_s));
+}
+
+void recursive_directory_iterator::__pop(error_code* ec) {
+ _LIBCPP_ASSERT(__imp_, "Popping the end iterator");
+ if (ec)
+ ec->clear();
+ __imp_->__stack_.pop();
+ if (__imp_->__stack_.size() == 0)
+ __imp_.reset();
+ else
+ __advance(ec);
+}
+
+directory_options recursive_directory_iterator::options() const {
+ return __imp_->__options_;
+}
+
+int recursive_directory_iterator::depth() const {
+ return __imp_->__stack_.size() - 1;
+}
+
+const directory_entry& recursive_directory_iterator::__dereference() const {
+ return __imp_->__stack_.top().__entry_;
+}
+
+recursive_directory_iterator&
+recursive_directory_iterator::__increment(error_code* ec) {
+ if (ec)
+ ec->clear();
+ if (recursion_pending()) {
+ if (__try_recursion(ec) || (ec && *ec))
+ return *this;
+ }
+ __rec_ = true;
+ __advance(ec);
+ return *this;
+}
+
+void recursive_directory_iterator::__advance(error_code* ec) {
+ ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
+
+ const directory_iterator end_it;
+ auto& stack = __imp_->__stack_;
+ error_code m_ec;
+ while (stack.size() > 0) {
+ if (stack.top().advance(m_ec))
+ return;
+ if (m_ec)
+ break;
+ stack.pop();
+ }
+
+ if (m_ec) {
+ path root = move(stack.top().__root_);
+ __imp_.reset();
+ err.report(m_ec, "at root \"%s\"", root);
+ } else {
+ __imp_.reset();
+ }
+}
+
+bool recursive_directory_iterator::__try_recursion(error_code* ec) {
+ ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
+
+ bool rec_sym = bool(options() & directory_options::follow_directory_symlink);
+
+ auto& curr_it = __imp_->__stack_.top();
+
+ bool skip_rec = false;
+ error_code m_ec;
+ if (!rec_sym) {
+ file_status st(curr_it.__entry_.__get_sym_ft(&m_ec));
+ if (m_ec && status_known(st))
+ m_ec.clear();
+ if (m_ec || is_symlink(st) || !is_directory(st))
+ skip_rec = true;
+ } else {
+ file_status st(curr_it.__entry_.__get_ft(&m_ec));
+ if (m_ec && status_known(st))
+ m_ec.clear();
+ if (m_ec || !is_directory(st))
+ skip_rec = true;
+ }
+
+ if (!skip_rec) {
+ __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec);
+ if (new_it.good()) {
+ __imp_->__stack_.push(move(new_it));
+ return true;
+ }
+ }
+ if (m_ec) {
+ const bool allow_eacess =
+ bool(__imp_->__options_ & directory_options::skip_permission_denied);
+ if (m_ec.value() == EACCES && allow_eacess) {
+ if (ec)
+ ec->clear();
+ } else {
+ path at_ent = move(curr_it.__entry_.__p_);
+ __imp_.reset();
+ err.report(m_ec, "attempting recursion into \"%s\"", at_ent);
+ }
+ }
+ return false;
+}
+
+} // namespace android::hardware::automotive::filesystem
+/* clang-format on */
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h b/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h
new file mode 100644
index 0000000..4f44661
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h
@@ -0,0 +1,441 @@
+//===----------------------------------------------------------------------===////
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===////
+/* clang-format off */
+#ifndef AUTO_FILESYSTEM_COMMON_H
+#define AUTO_FILESYSTEM_COMMON_H
+
+#include "automotive/filesystem"
+#include <array>
+#include <chrono>
+#include <cstdlib>
+#include <climits>
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/time.h> // for ::utimes as used in __last_write_time
+#include <fcntl.h> /* values for fchmodat */
+
+#if !defined(__APPLE__)
+// We can use the presence of UTIME_OMIT to detect platforms that provide
+// utimensat.
+#if defined(UTIME_OMIT)
+#define _LIBCPP_USE_UTIMENSAT
+#endif
+#endif
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+namespace android::hardware::automotive::filesystem {
+using namespace std::chrono;
+
+using std::error_code;
+using std::is_floating_point;
+using std::micro;
+using std::nano;
+using std::ratio;
+
+namespace detail {
+namespace {
+
+static string format_string_imp(const char* msg, ...) {
+ // we might need a second shot at this, so pre-emptivly make a copy
+ struct GuardVAList {
+ va_list& target;
+ bool active = true;
+ GuardVAList(va_list& target) : target(target), active(true) {}
+ void clear() {
+ if (active)
+ va_end(target);
+ active = false;
+ }
+ ~GuardVAList() {
+ if (active)
+ va_end(target);
+ }
+ };
+ va_list args;
+ va_start(args, msg);
+ GuardVAList args_guard(args);
+
+ va_list args_cp;
+ va_copy(args_cp, args);
+ GuardVAList args_copy_guard(args_cp);
+
+ std::string result;
+
+ array<char, 256> local_buff;
+ size_t size_with_null = local_buff.size();
+ auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp);
+
+ args_copy_guard.clear();
+
+ // handle empty expansion
+ if (ret == 0)
+ return result;
+ if (static_cast<size_t>(ret) < size_with_null) {
+ result.assign(local_buff.data(), static_cast<size_t>(ret));
+ return result;
+ }
+
+ // we did not provide a long enough buffer on our first attempt. The
+ // return value is the number of bytes (excluding the null byte) that are
+ // needed for formatting.
+ size_with_null = static_cast<size_t>(ret) + 1;
+ result.__resize_default_init(size_with_null - 1);
+ ret = ::vsnprintf(&result[0], size_with_null, msg, args);
+ _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO");
+
+ return result;
+}
+
+const char* unwrap(string const& s) { return s.c_str(); }
+const char* unwrap(path const& p) { return p.native().c_str(); }
+template <class Arg>
+Arg const& unwrap(Arg const& a) {
+ static_assert(!is_class<Arg>::value, "cannot pass class here");
+ return a;
+}
+
+template <class... Args>
+string format_string(const char* fmt, Args const&... args) {
+ return format_string_imp(fmt, unwrap(args)...);
+}
+
+error_code capture_errno() {
+ _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
+ return error_code(errno, generic_category());
+}
+
+template <class T>
+T error_value();
+template <>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {}
+template <>
+bool error_value<bool>() {
+ return false;
+}
+template <>
+uintmax_t error_value<uintmax_t>() {
+ return uintmax_t(-1);
+}
+template <>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
+ return file_time_type::min();
+}
+template <>
+path error_value<path>() {
+ return {};
+}
+
+template <class T>
+struct ErrorHandler {
+ const char* func_name;
+ error_code* ec = nullptr;
+ const path* p1 = nullptr;
+ const path* p2 = nullptr;
+
+ ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
+ const path* p2 = nullptr)
+ : func_name(fname), ec(ec), p1(p1), p2(p2) {
+ if (ec)
+ ec->clear();
+ }
+
+ T report(const error_code& m_ec) const {
+ if (ec) {
+ *ec = m_ec;
+ return error_value<T>();
+ }
+ string what = string("in ") + func_name;
+ switch (bool(p1) + bool(p2)) {
+ case 0:
+ __throw_filesystem_error(what, m_ec);
+ case 1:
+ __throw_filesystem_error(what, *p1, m_ec);
+ case 2:
+ __throw_filesystem_error(what, *p1, *p2, m_ec);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ template <class... Args>
+ T report(const error_code& m_ec, const char* msg, Args const&... args) const {
+ if (ec) {
+ *ec = m_ec;
+ return error_value<T>();
+ }
+ string what =
+ string("in ") + func_name + ": " + format_string(msg, args...);
+ switch (bool(p1) + bool(p2)) {
+ case 0:
+ __throw_filesystem_error(what, m_ec);
+ case 1:
+ __throw_filesystem_error(what, *p1, m_ec);
+ case 2:
+ __throw_filesystem_error(what, *p1, *p2, m_ec);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ T report(errc const& err) const { return report(make_error_code(err)); }
+
+ template <class... Args>
+ T report(errc const& err, const char* msg, Args const&... args) const {
+ return report(make_error_code(err), msg, args...);
+ }
+
+private:
+ ErrorHandler(ErrorHandler const&) = delete;
+ ErrorHandler& operator=(ErrorHandler const&) = delete;
+};
+
+using chrono::duration;
+using chrono::duration_cast;
+
+using TimeSpec = struct ::timespec;
+using StatT = struct ::stat;
+
+template <class FileTimeT, class TimeT,
+ bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
+struct time_util_base {
+ using rep = typename FileTimeT::rep;
+ using fs_duration = typename FileTimeT::duration;
+ using fs_seconds = duration<rep>;
+ using fs_nanoseconds = duration<rep, nano>;
+ using fs_microseconds = duration<rep, micro>;
+
+ static constexpr rep max_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
+
+ static constexpr rep max_nsec =
+ duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
+ fs_seconds(max_seconds))
+ .count();
+
+ static constexpr rep min_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
+
+ static constexpr rep min_nsec_timespec =
+ duration_cast<fs_nanoseconds>(
+ (FileTimeT::duration::min() - fs_seconds(min_seconds)) +
+ fs_seconds(1))
+ .count();
+
+private:
+#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
+ static constexpr fs_duration get_min_nsecs() {
+ return duration_cast<fs_duration>(
+ fs_nanoseconds(min_nsec_timespec) -
+ duration_cast<fs_nanoseconds>(fs_seconds(1)));
+ }
+ // Static assert that these values properly round trip.
+ static_assert(fs_seconds(min_seconds) + get_min_nsecs() ==
+ FileTimeT::duration::min(),
+ "value doesn't roundtrip");
+
+ static constexpr bool check_range() {
+ // This kinda sucks, but it's what happens when we don't have __int128_t.
+ if (sizeof(TimeT) == sizeof(rep)) {
+ typedef duration<long long, ratio<3600 * 24 * 365> > Years;
+ return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) &&
+ duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250);
+ }
+ return max_seconds >= numeric_limits<TimeT>::max() &&
+ min_seconds <= numeric_limits<TimeT>::min();
+ }
+ static_assert(check_range(), "the representable range is unacceptable small");
+#endif
+};
+
+template <class FileTimeT, class TimeT>
+struct time_util_base<FileTimeT, TimeT, true> {
+ using rep = typename FileTimeT::rep;
+ using fs_duration = typename FileTimeT::duration;
+ using fs_seconds = duration<rep>;
+ using fs_nanoseconds = duration<rep, nano>;
+ using fs_microseconds = duration<rep, micro>;
+
+ static const rep max_seconds;
+ static const rep max_nsec;
+ static const rep min_seconds;
+ static const rep min_nsec_timespec;
+};
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep
+ time_util_base<FileTimeT, TimeT, true>::max_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
+ duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
+ fs_seconds(max_seconds))
+ .count();
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep
+ time_util_base<FileTimeT, TimeT, true>::min_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep
+ time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
+ duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
+ fs_seconds(min_seconds)) +
+ fs_seconds(1))
+ .count();
+
+template <class FileTimeT, class TimeT, class TimeSpecT>
+struct time_util : time_util_base<FileTimeT, TimeT> {
+ using Base = time_util_base<FileTimeT, TimeT>;
+ using Base::max_nsec;
+ using Base::max_seconds;
+ using Base::min_nsec_timespec;
+ using Base::min_seconds;
+
+ using typename Base::fs_duration;
+ using typename Base::fs_microseconds;
+ using typename Base::fs_nanoseconds;
+ using typename Base::fs_seconds;
+
+public:
+ template <class CType, class ChronoType>
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
+ ChronoType time) {
+ using Lim = numeric_limits<CType>;
+ if (time > Lim::max() || time < Lim::min())
+ return false;
+ *out = static_cast<CType>(time);
+ return true;
+ }
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
+ if (tm.tv_sec >= 0) {
+ return tm.tv_sec < max_seconds ||
+ (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
+ } else if (tm.tv_sec == (min_seconds - 1)) {
+ return tm.tv_nsec >= min_nsec_timespec;
+ } else {
+ return tm.tv_sec >= min_seconds;
+ }
+ }
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
+ auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
+ auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
+ if (nsecs.count() < 0) {
+ secs = secs + fs_seconds(1);
+ nsecs = nsecs + fs_seconds(1);
+ }
+ using TLim = numeric_limits<TimeT>;
+ if (secs.count() >= 0)
+ return secs.count() <= TLim::max();
+ return secs.count() >= TLim::min();
+ }
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
+ convert_from_timespec(TimeSpecT tm) {
+ if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
+ return FileTimeT(fs_seconds(tm.tv_sec) +
+ duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
+ } else { // tm.tv_sec < 0
+ auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
+ fs_nanoseconds(tm.tv_nsec));
+ auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
+ return FileTimeT(Dur);
+ }
+ }
+
+ template <class SubSecT>
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
+ set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
+ auto dur = tp.time_since_epoch();
+ auto sec_dur = duration_cast<fs_seconds>(dur);
+ auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
+ // The tv_nsec and tv_usec fields must not be negative so adjust accordingly
+ if (subsec_dur.count() < 0) {
+ if (sec_dur.count() > min_seconds) {
+ sec_dur = sec_dur - fs_seconds(1);
+ subsec_dur = subsec_dur + fs_seconds(1);
+ } else {
+ subsec_dur = fs_nanoseconds::zero();
+ }
+ }
+ return checked_set(sec_out, sec_dur.count()) &&
+ checked_set(subsec_out, subsec_dur.count());
+ }
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
+ FileTimeT tp) {
+ if (!is_representable(tp))
+ return false;
+ return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
+ }
+};
+
+using fs_time = time_util<file_time_type, time_t, TimeSpec>;
+
+#if defined(__APPLE__)
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
+TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
+#else
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
+TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
+#endif
+
+// allow the utimes implementation to compile even it we're not going
+// to use it.
+
+bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
+ error_code& ec) {
+ using namespace chrono;
+ auto Convert = [](long nsec) {
+ using int_type = decltype(std::declval< ::timeval>().tv_usec);
+ auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
+ return static_cast<int_type>(dur);
+ };
+ struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
+ {TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
+ if (::utimes(p.c_str(), ConvertedTS) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ return false;
+}
+
+#if defined(_LIBCPP_USE_UTIMENSAT)
+bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS,
+ error_code& ec) {
+ if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ return false;
+}
+#endif
+
+bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS,
+ error_code& ec) {
+#if !defined(_LIBCPP_USE_UTIMENSAT)
+ return posix_utimes(p, TS, ec);
+#else
+ return posix_utimensat(p, TS, ec);
+#endif
+}
+
+} // namespace
+} // end namespace detail
+
+} // namespace android::hardware::automotive::filesystem
+
+#endif // AUTO_FILESYSTEM_COMMON_H
+/* clang-format on */
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp b/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp
new file mode 100644
index 0000000..404c0bd
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp
@@ -0,0 +1,1773 @@
+//===--------------------- filesystem/ops.cpp -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/* clang-format off */
+#include "automotive/filesystem"
+#include <array>
+#include <iterator>
+#include <fstream>
+#include <random> /* for unique_path */
+#include <string_view>
+#include <type_traits>
+#include <vector>
+#include <cstdlib>
+#include <climits>
+
+#include "filesystem_common.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <time.h>
+#include <fcntl.h> /* values for fchmodat */
+
+#if defined(__linux__)
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+#include <sys/sendfile.h>
+#define _LIBCPP_USE_SENDFILE
+#endif
+#elif defined(__APPLE__) || __has_include(<copyfile.h>)
+#include <copyfile.h>
+#define _LIBCPP_USE_COPYFILE
+#endif
+
+#if !defined(__APPLE__)
+#define _LIBCPP_USE_CLOCK_GETTIME
+#endif
+
+#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
+#include <sys/time.h> // for gettimeofday and timeval
+#endif // !defined(CLOCK_REALTIME)
+
+#if defined(_LIBCPP_COMPILER_GCC)
+#if _GNUC_VER < 500
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+#endif
+
+namespace android::hardware::automotive::filesystem {
+
+#ifdef _VSTD_FS
+#pragma push_macro("_VSTD_FS")
+#else
+#define _LIBAUTO_UNDEF_VSTD_FS
+#endif
+#define _VSTD_FS android::hardware::automotive::filesystem
+
+namespace {
+namespace parser {
+
+using string_view_t = path::__string_view;
+using string_view_pair = pair<string_view_t, string_view_t>;
+using PosPtr = path::value_type const*;
+
+struct PathParser {
+ enum ParserState : unsigned char {
+ // Zero is a special sentinel value used by default constructed iterators.
+ PS_BeforeBegin = path::iterator::_BeforeBegin,
+ PS_InRootName = path::iterator::_InRootName,
+ PS_InRootDir = path::iterator::_InRootDir,
+ PS_InFilenames = path::iterator::_InFilenames,
+ PS_InTrailingSep = path::iterator::_InTrailingSep,
+ PS_AtEnd = path::iterator::_AtEnd
+ };
+
+ const string_view_t Path;
+ string_view_t RawEntry;
+ ParserState State;
+
+private:
+ PathParser(string_view_t P, ParserState State) noexcept : Path(P),
+ State(State) {}
+
+public:
+ PathParser(string_view_t P, string_view_t E, unsigned char S)
+ : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
+ // S cannot be '0' or PS_BeforeBegin.
+ }
+
+ static PathParser CreateBegin(string_view_t P) noexcept {
+ PathParser PP(P, PS_BeforeBegin);
+ PP.increment();
+ return PP;
+ }
+
+ static PathParser CreateEnd(string_view_t P) noexcept {
+ PathParser PP(P, PS_AtEnd);
+ return PP;
+ }
+
+ PosPtr peek() const noexcept {
+ auto TkEnd = getNextTokenStartPos();
+ auto End = getAfterBack();
+ return TkEnd == End ? nullptr : TkEnd;
+ }
+
+ void increment() noexcept {
+ const PosPtr End = getAfterBack();
+ const PosPtr Start = getNextTokenStartPos();
+ if (Start == End)
+ return makeState(PS_AtEnd);
+
+ switch (State) {
+ case PS_BeforeBegin: {
+ PosPtr TkEnd = consumeSeparator(Start, End);
+ if (TkEnd)
+ return makeState(PS_InRootDir, Start, TkEnd);
+ else
+ return makeState(PS_InFilenames, Start, consumeName(Start, End));
+ }
+ case PS_InRootDir:
+ return makeState(PS_InFilenames, Start, consumeName(Start, End));
+
+ case PS_InFilenames: {
+ PosPtr SepEnd = consumeSeparator(Start, End);
+ if (SepEnd != End) {
+ PosPtr TkEnd = consumeName(SepEnd, End);
+ if (TkEnd)
+ return makeState(PS_InFilenames, SepEnd, TkEnd);
+ }
+ return makeState(PS_InTrailingSep, Start, SepEnd);
+ }
+
+ case PS_InTrailingSep:
+ return makeState(PS_AtEnd);
+
+ case PS_InRootName:
+ case PS_AtEnd:
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+
+ void decrement() noexcept {
+ const PosPtr REnd = getBeforeFront();
+ const PosPtr RStart = getCurrentTokenStartPos() - 1;
+ if (RStart == REnd) // we're decrementing the begin
+ return makeState(PS_BeforeBegin);
+
+ switch (State) {
+ case PS_AtEnd: {
+ // Try to consume a trailing separator or root directory first.
+ if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
+ if (SepEnd == REnd)
+ return makeState(PS_InRootDir, Path.data(), RStart + 1);
+ return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
+ } else {
+ PosPtr TkStart = consumeName(RStart, REnd);
+ return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
+ }
+ }
+ case PS_InTrailingSep:
+ return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1,
+ RStart + 1);
+ case PS_InFilenames: {
+ PosPtr SepEnd = consumeSeparator(RStart, REnd);
+ if (SepEnd == REnd)
+ return makeState(PS_InRootDir, Path.data(), RStart + 1);
+ PosPtr TkEnd = consumeName(SepEnd, REnd);
+ return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
+ }
+ case PS_InRootDir:
+ // return makeState(PS_InRootName, Path.data(), RStart + 1);
+ case PS_InRootName:
+ case PS_BeforeBegin:
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+
+ /// \brief Return a view with the "preferred representation" of the current
+ /// element. For example trailing separators are represented as a '.'
+ string_view_t operator*() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ case PS_AtEnd:
+ return "";
+ case PS_InRootDir:
+ return "/";
+ case PS_InTrailingSep:
+ return "";
+ case PS_InRootName:
+ case PS_InFilenames:
+ return RawEntry;
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ explicit operator bool() const noexcept {
+ return State != PS_BeforeBegin && State != PS_AtEnd;
+ }
+
+ PathParser& operator++() noexcept {
+ increment();
+ return *this;
+ }
+
+ PathParser& operator--() noexcept {
+ decrement();
+ return *this;
+ }
+
+ bool atEnd() const noexcept {
+ return State == PS_AtEnd;
+ }
+
+ bool inRootDir() const noexcept {
+ return State == PS_InRootDir;
+ }
+
+ bool inRootName() const noexcept {
+ return State == PS_InRootName;
+ }
+
+ bool inRootPath() const noexcept {
+ return inRootName() || inRootDir();
+ }
+
+private:
+ void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
+ State = NewState;
+ RawEntry = string_view_t(Start, End - Start);
+ }
+ void makeState(ParserState NewState) noexcept {
+ State = NewState;
+ RawEntry = {};
+ }
+
+ PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); }
+
+ PosPtr getBeforeFront() const noexcept { return Path.data() - 1; }
+
+ /// \brief Return a pointer to the first character after the currently
+ /// lexed element.
+ PosPtr getNextTokenStartPos() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ return Path.data();
+ case PS_InRootName:
+ case PS_InRootDir:
+ case PS_InFilenames:
+ return &RawEntry.back() + 1;
+ case PS_InTrailingSep:
+ case PS_AtEnd:
+ return getAfterBack();
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ /// \brief Return a pointer to the first character in the currently lexed
+ /// element.
+ PosPtr getCurrentTokenStartPos() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ case PS_InRootName:
+ return &Path.front();
+ case PS_InRootDir:
+ case PS_InFilenames:
+ case PS_InTrailingSep:
+ return &RawEntry.front();
+ case PS_AtEnd:
+ return &Path.back() + 1;
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
+ if (P == End || *P != '/')
+ return nullptr;
+ const int Inc = P < End ? 1 : -1;
+ P += Inc;
+ while (P != End && *P == '/')
+ P += Inc;
+ return P;
+ }
+
+ PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
+ if (P == End || *P == '/')
+ return nullptr;
+ const int Inc = P < End ? 1 : -1;
+ P += Inc;
+ while (P != End && *P != '/')
+ P += Inc;
+ return P;
+ }
+};
+
+string_view_pair separate_filename(string_view_t const& s) {
+ if (s == "." || s == ".." || s.empty())
+ return string_view_pair{s, ""};
+ auto pos = s.find_last_of('.');
+ if (pos == string_view_t::npos || pos == 0)
+ return string_view_pair{s, string_view_t{}};
+ return string_view_pair{s.substr(0, pos), s.substr(pos)};
+}
+
+string_view_t createView(PosPtr S, PosPtr E) noexcept {
+ return {S, static_cast<size_t>(E - S) + 1};
+}
+
+} // namespace parser
+} // namespace
+
+// POSIX HELPERS
+
+namespace detail {
+namespace {
+
+using value_type = path::value_type;
+using string_type = path::string_type;
+
+struct FileDescriptor {
+ const path& name;
+ int fd = -1;
+ StatT m_stat;
+ file_status m_status;
+
+ template <class... Args>
+ static FileDescriptor create(const path* p, error_code& ec, Args... args) {
+ ec.clear();
+ int fd;
+ if ((fd = ::open(p->c_str(), args...)) == -1) {
+ ec = capture_errno();
+ return FileDescriptor{p};
+ }
+ return FileDescriptor(p, fd);
+ }
+
+ template <class... Args>
+ static FileDescriptor create_with_status(const path* p, error_code& ec,
+ Args... args) {
+ FileDescriptor fd = create(p, ec, args...);
+ if (!ec)
+ fd.refresh_status(ec);
+
+ return fd;
+ }
+
+ file_status get_status() const { return m_status; }
+ StatT const& get_stat() const { return m_stat; }
+
+ bool status_known() const { return _VSTD_FS::status_known(m_status); }
+
+ file_status refresh_status(error_code& ec);
+
+ void close() noexcept {
+ if (fd != -1)
+ ::close(fd);
+ fd = -1;
+ }
+
+ FileDescriptor(FileDescriptor&& other)
+ : name(other.name), fd(other.fd), m_stat(other.m_stat),
+ m_status(other.m_status) {
+ other.fd = -1;
+ other.m_status = file_status{};
+ }
+
+ ~FileDescriptor() { close(); }
+
+ FileDescriptor(FileDescriptor const&) = delete;
+ FileDescriptor& operator=(FileDescriptor const&) = delete;
+
+private:
+ explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {}
+};
+
+perms posix_get_perms(const StatT& st) noexcept {
+ return static_cast<perms>(st.st_mode) & perms::mask;
+}
+
+::mode_t posix_convert_perms(perms prms) {
+ return static_cast< ::mode_t>(prms & perms::mask);
+}
+
+file_status create_file_status(error_code& m_ec, path const& p,
+ const StatT& path_stat, error_code* ec) {
+ if (ec)
+ *ec = m_ec;
+ if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
+ return file_status(file_type::not_found);
+ } else if (m_ec) {
+ ErrorHandler<void> err("posix_stat", ec, &p);
+ err.report(m_ec, "failed to determine attributes for the specified path");
+ return file_status(file_type::none);
+ }
+ // else
+
+ file_status fs_tmp;
+ auto const mode = path_stat.st_mode;
+ if (S_ISLNK(mode))
+ fs_tmp.type(file_type::symlink);
+ else if (S_ISREG(mode))
+ fs_tmp.type(file_type::regular);
+ else if (S_ISDIR(mode))
+ fs_tmp.type(file_type::directory);
+ else if (S_ISBLK(mode))
+ fs_tmp.type(file_type::block);
+ else if (S_ISCHR(mode))
+ fs_tmp.type(file_type::character);
+ else if (S_ISFIFO(mode))
+ fs_tmp.type(file_type::fifo);
+ else if (S_ISSOCK(mode))
+ fs_tmp.type(file_type::socket);
+ else
+ fs_tmp.type(file_type::unknown);
+
+ fs_tmp.permissions(detail::posix_get_perms(path_stat));
+ return fs_tmp;
+}
+
+file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) {
+ error_code m_ec;
+ if (::stat(p.c_str(), &path_stat) == -1)
+ m_ec = detail::capture_errno();
+ return create_file_status(m_ec, p, path_stat, ec);
+}
+
+file_status posix_stat(path const& p, error_code* ec) {
+ StatT path_stat;
+ return posix_stat(p, path_stat, ec);
+}
+
+file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) {
+ error_code m_ec;
+ if (::lstat(p.c_str(), &path_stat) == -1)
+ m_ec = detail::capture_errno();
+ return create_file_status(m_ec, p, path_stat, ec);
+}
+
+file_status posix_lstat(path const& p, error_code* ec) {
+ StatT path_stat;
+ return posix_lstat(p, path_stat, ec);
+}
+
+bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) {
+ if (::ftruncate(fd.fd, to_size) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ ec.clear();
+ return false;
+}
+
+bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
+ if (::fchmod(fd.fd, st.st_mode) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ ec.clear();
+ return false;
+}
+
+bool stat_equivalent(const StatT& st1, const StatT& st2) {
+ return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+}
+
+file_status FileDescriptor::refresh_status(error_code& ec) {
+ // FD must be open and good.
+ m_status = file_status{};
+ m_stat = {};
+ error_code m_ec;
+ if (::fstat(fd, &m_stat) == -1)
+ m_ec = capture_errno();
+ m_status = create_file_status(m_ec, name, m_stat, &ec);
+ return m_status;
+}
+} // namespace
+} // end namespace detail
+
+using detail::capture_errno;
+using detail::ErrorHandler;
+using detail::StatT;
+using detail::TimeSpec;
+using parser::createView;
+using parser::PathParser;
+using parser::string_view_t;
+
+const bool _FilesystemClock::is_steady;
+
+_FilesystemClock::time_point _FilesystemClock::now() noexcept {
+ typedef chrono::duration<rep> __secs;
+#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
+ typedef chrono::duration<rep, nano> __nsecs;
+ struct timespec tp;
+ if (0 != clock_gettime(CLOCK_REALTIME, &tp))
+ __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
+ return time_point(__secs(tp.tv_sec) +
+ chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
+#else
+ typedef chrono::duration<rep, micro> __microsecs;
+ timeval tv;
+ gettimeofday(&tv, 0);
+ return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec));
+#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
+}
+
+filesystem_error::~filesystem_error() {}
+
+void filesystem_error::__create_what(int __num_paths) {
+ const char* derived_what = system_error::what();
+ __storage_->__what_ = [&]() -> string {
+ const char* p1 = path1().native().empty() ? "\"\"" : path1().c_str();
+ const char* p2 = path2().native().empty() ? "\"\"" : path2().c_str();
+ switch (__num_paths) {
+ default:
+ return detail::format_string("filesystem error: %s", derived_what);
+ case 1:
+ return detail::format_string("filesystem error: %s [%s]", derived_what,
+ p1);
+ case 2:
+ return detail::format_string("filesystem error: %s [%s] [%s]",
+ derived_what, p1, p2);
+ }
+ }();
+}
+
+static path __do_absolute(const path& p, path* cwd, error_code* ec) {
+ if (ec)
+ ec->clear();
+ if (p.is_absolute())
+ return p;
+ *cwd = __current_path(ec);
+ if (ec && *ec)
+ return {};
+ return (*cwd) / p;
+}
+
+path __absolute(const path& p, error_code* ec) {
+ path cwd;
+ return __do_absolute(p, &cwd, ec);
+}
+
+path __canonical(path const& orig_p, error_code* ec) {
+ path cwd;
+ ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
+
+ path p = __do_absolute(orig_p, &cwd, ec);
+ char buff[PATH_MAX + 1];
+ char* ret;
+ if ((ret = ::realpath(p.c_str(), buff)) == nullptr)
+ return err.report(capture_errno());
+ return {ret};
+}
+
+void __copy(const path& from, const path& to, copy_options options,
+ error_code* ec) {
+ ErrorHandler<void> err("copy", ec, &from, &to);
+
+ const bool sym_status = bool(
+ options & (copy_options::create_symlinks | copy_options::skip_symlinks));
+
+ const bool sym_status2 = bool(options & copy_options::copy_symlinks);
+
+ error_code m_ec1;
+ StatT f_st = {};
+ const file_status f = sym_status || sym_status2
+ ? detail::posix_lstat(from, f_st, &m_ec1)
+ : detail::posix_stat(from, f_st, &m_ec1);
+ if (m_ec1)
+ return err.report(m_ec1);
+
+ StatT t_st = {};
+ const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
+ : detail::posix_stat(to, t_st, &m_ec1);
+
+ if (not status_known(t))
+ return err.report(m_ec1);
+
+ if (!exists(f) || is_other(f) || is_other(t) ||
+ (is_directory(f) && is_regular_file(t)) ||
+ detail::stat_equivalent(f_st, t_st)) {
+ return err.report(errc::function_not_supported);
+ }
+
+ if (ec)
+ ec->clear();
+
+ if (is_symlink(f)) {
+ if (bool(copy_options::skip_symlinks & options)) {
+ // do nothing
+ } else if (not exists(t)) {
+ __copy_symlink(from, to, ec);
+ } else {
+ return err.report(errc::file_exists);
+ }
+ return;
+ } else if (is_regular_file(f)) {
+ if (bool(copy_options::directories_only & options)) {
+ // do nothing
+ } else if (bool(copy_options::create_symlinks & options)) {
+ __create_symlink(from, to, ec);
+ } else if (bool(copy_options::create_hard_links & options)) {
+ __create_hard_link(from, to, ec);
+ } else if (is_directory(t)) {
+ __copy_file(from, to / from.filename(), options, ec);
+ } else {
+ __copy_file(from, to, options, ec);
+ }
+ return;
+ } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
+ return err.report(errc::is_a_directory);
+ } else if (is_directory(f) && (bool(copy_options::recursive & options) ||
+ copy_options::none == options)) {
+
+ if (!exists(t)) {
+ // create directory to with attributes from 'from'.
+ __create_directory(to, from, ec);
+ if (ec && *ec) {
+ return;
+ }
+ }
+ directory_iterator it =
+ ec ? directory_iterator(from, *ec) : directory_iterator(from);
+ if (ec && *ec) {
+ return;
+ }
+ error_code m_ec2;
+ for (; it != directory_iterator(); it.increment(m_ec2)) {
+ if (m_ec2) {
+ return err.report(m_ec2);
+ }
+ __copy(it->path(), to / it->path().filename(),
+ options | copy_options::__in_recursive_copy, ec);
+ if (ec && *ec) {
+ return;
+ }
+ }
+ }
+}
+
+namespace detail {
+namespace {
+
+#ifdef _LIBCPP_USE_SENDFILE
+bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
+ error_code& ec) {
+
+ size_t count = read_fd.get_stat().st_size;
+ do {
+ ssize_t res;
+ if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) {
+ ec = capture_errno();
+ return false;
+ }
+ count -= res;
+ } while (count > 0);
+
+ ec.clear();
+
+ return true;
+}
+#elif defined(_LIBCPP_USE_COPYFILE)
+bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
+ error_code& ec) {
+ struct CopyFileState {
+ copyfile_state_t state;
+ CopyFileState() { state = copyfile_state_alloc(); }
+ ~CopyFileState() { copyfile_state_free(state); }
+
+ private:
+ CopyFileState(CopyFileState const&) = delete;
+ CopyFileState& operator=(CopyFileState const&) = delete;
+ };
+
+ CopyFileState cfs;
+ if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
+ ec = capture_errno();
+ return false;
+ }
+
+ ec.clear();
+ return true;
+}
+#endif
+
+// Note: This function isn't guarded by ifdef's even though it may be unused
+// in order to assure it still compiles.
+__attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd,
+ FileDescriptor& write_fd,
+ error_code& ec) {
+ ifstream in;
+ in.__open(read_fd.fd, ios::binary);
+ if (!in.is_open()) {
+ // This assumes that __open didn't reset the error code.
+ ec = capture_errno();
+ return false;
+ }
+ ofstream out;
+ out.__open(write_fd.fd, ios::binary);
+ if (!out.is_open()) {
+ ec = capture_errno();
+ return false;
+ }
+
+ if (in.good() && out.good()) {
+ using InIt = istreambuf_iterator<char>;
+ using OutIt = ostreambuf_iterator<char>;
+ InIt bin(in);
+ InIt ein;
+ OutIt bout(out);
+ copy(bin, ein, bout);
+ }
+ if (out.fail() || in.fail()) {
+ ec = make_error_code(errc::io_error);
+ return false;
+ }
+
+ ec.clear();
+ return true;
+}
+
+bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) {
+#if defined(_LIBCPP_USE_SENDFILE)
+ return copy_file_impl_sendfile(from, to, ec);
+#elif defined(_LIBCPP_USE_COPYFILE)
+ return copy_file_impl_copyfile(from, to, ec);
+#else
+ return copy_file_impl_default(from, to, ec);
+#endif
+}
+
+} // namespace
+} // namespace detail
+
+bool __copy_file(const path& from, const path& to, copy_options options,
+ error_code* ec) {
+ using detail::FileDescriptor;
+ ErrorHandler<bool> err("copy_file", ec, &to, &from);
+
+ error_code m_ec;
+ FileDescriptor from_fd =
+ FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK);
+ if (m_ec)
+ return err.report(m_ec);
+
+ auto from_st = from_fd.get_status();
+ StatT const& from_stat = from_fd.get_stat();
+ if (!is_regular_file(from_st)) {
+ if (not m_ec)
+ m_ec = make_error_code(errc::not_supported);
+ return err.report(m_ec);
+ }
+
+ const bool skip_existing = bool(copy_options::skip_existing & options);
+ const bool update_existing = bool(copy_options::update_existing & options);
+ const bool overwrite_existing =
+ bool(copy_options::overwrite_existing & options);
+
+ StatT to_stat_path;
+ file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec);
+ if (!status_known(to_st))
+ return err.report(m_ec);
+
+ const bool to_exists = exists(to_st);
+ if (to_exists && !is_regular_file(to_st))
+ return err.report(errc::not_supported);
+
+ if (to_exists && detail::stat_equivalent(from_stat, to_stat_path))
+ return err.report(errc::file_exists);
+
+ if (to_exists && skip_existing)
+ return false;
+
+ bool ShouldCopy = [&]() {
+ if (to_exists && update_existing) {
+ auto from_time = detail::extract_mtime(from_stat);
+ auto to_time = detail::extract_mtime(to_stat_path);
+ if (from_time.tv_sec < to_time.tv_sec)
+ return false;
+ if (from_time.tv_sec == to_time.tv_sec &&
+ from_time.tv_nsec <= to_time.tv_nsec)
+ return false;
+ return true;
+ }
+ if (!to_exists || overwrite_existing)
+ return true;
+ return err.report(errc::file_exists);
+ }();
+ if (!ShouldCopy)
+ return false;
+
+ // Don't truncate right away. We may not be opening the file we originally
+ // looked at; we'll check this later.
+ int to_open_flags = O_WRONLY;
+ if (!to_exists)
+ to_open_flags |= O_CREAT;
+ FileDescriptor to_fd = FileDescriptor::create_with_status(
+ &to, m_ec, to_open_flags, from_stat.st_mode);
+ if (m_ec)
+ return err.report(m_ec);
+
+ if (to_exists) {
+ // Check that the file we initially stat'ed is equivalent to the one
+ // we opened.
+ // FIXME: report this better.
+ if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat()))
+ return err.report(errc::bad_file_descriptor);
+
+ // Set the permissions and truncate the file we opened.
+ if (detail::posix_fchmod(to_fd, from_stat, m_ec))
+ return err.report(m_ec);
+ if (detail::posix_ftruncate(to_fd, 0, m_ec))
+ return err.report(m_ec);
+ }
+
+ if (!copy_file_impl(from_fd, to_fd, m_ec)) {
+ // FIXME: Remove the dest file if we failed, and it didn't exist previously.
+ return err.report(m_ec);
+ }
+
+ return true;
+}
+
+void __copy_symlink(const path& existing_symlink, const path& new_symlink,
+ error_code* ec) {
+ const path real_path(__read_symlink(existing_symlink, ec));
+ if (ec && *ec) {
+ return;
+ }
+ // NOTE: proposal says you should detect if you should call
+ // create_symlink or create_directory_symlink. I don't think this
+ // is needed with POSIX
+ __create_symlink(real_path, new_symlink, ec);
+}
+
+bool __create_directories(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("create_directories", ec, &p);
+
+ error_code m_ec;
+ auto const st = detail::posix_stat(p, &m_ec);
+ if (!status_known(st))
+ return err.report(m_ec);
+ else if (is_directory(st))
+ return false;
+ else if (exists(st))
+ return err.report(errc::file_exists);
+
+ const path parent = p.parent_path();
+ if (!parent.empty()) {
+ const file_status parent_st = status(parent, m_ec);
+ if (not status_known(parent_st))
+ return err.report(m_ec);
+ if (not exists(parent_st)) {
+ __create_directories(parent, ec);
+ if (ec && *ec) {
+ return false;
+ }
+ }
+ }
+ return __create_directory(p, ec);
+}
+
+bool __create_directory(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("create_directory", ec, &p);
+
+ if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
+ return true;
+ if (errno != EEXIST)
+ err.report(capture_errno());
+ return false;
+}
+
+bool __create_directory(path const& p, path const& attributes, error_code* ec) {
+ ErrorHandler<bool> err("create_directory", ec, &p, &attributes);
+
+ StatT attr_stat;
+ error_code mec;
+ auto st = detail::posix_stat(attributes, attr_stat, &mec);
+ if (!status_known(st))
+ return err.report(mec);
+ if (!is_directory(st))
+ return err.report(errc::not_a_directory,
+ "the specified attribute path is invalid");
+
+ if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
+ return true;
+ if (errno != EEXIST)
+ err.report(capture_errno());
+ return false;
+}
+
+void __create_directory_symlink(path const& from, path const& to,
+ error_code* ec) {
+ ErrorHandler<void> err("create_directory_symlink", ec, &from, &to);
+ if (::symlink(from.c_str(), to.c_str()) != 0)
+ return err.report(capture_errno());
+}
+
+void __create_hard_link(const path& from, const path& to, error_code* ec) {
+ ErrorHandler<void> err("create_hard_link", ec, &from, &to);
+ if (::link(from.c_str(), to.c_str()) == -1)
+ return err.report(capture_errno());
+}
+
+void __create_symlink(path const& from, path const& to, error_code* ec) {
+ ErrorHandler<void> err("create_symlink", ec, &from, &to);
+ if (::symlink(from.c_str(), to.c_str()) == -1)
+ return err.report(capture_errno());
+}
+
+path __current_path(error_code* ec) {
+ ErrorHandler<path> err("current_path", ec);
+
+ auto size = ::pathconf(".", _PC_PATH_MAX);
+ _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
+
+ auto buff = unique_ptr<char[]>(new char[size + 1]);
+ char* ret;
+ if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr)
+ return err.report(capture_errno(), "call to getcwd failed");
+
+ return {buff.get()};
+}
+
+void __current_path(const path& p, error_code* ec) {
+ ErrorHandler<void> err("current_path", ec, &p);
+ if (::chdir(p.c_str()) == -1)
+ err.report(capture_errno());
+}
+
+bool __equivalent(const path& p1, const path& p2, error_code* ec) {
+ ErrorHandler<bool> err("equivalent", ec, &p1, &p2);
+
+ error_code ec1, ec2;
+ StatT st1 = {}, st2 = {};
+ auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
+ if (!exists(s1))
+ return err.report(errc::not_supported);
+ auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
+ if (!exists(s2))
+ return err.report(errc::not_supported);
+
+ return detail::stat_equivalent(st1, st2);
+}
+
+uintmax_t __file_size(const path& p, error_code* ec) {
+ ErrorHandler<uintmax_t> err("file_size", ec, &p);
+
+ error_code m_ec;
+ StatT st;
+ file_status fst = detail::posix_stat(p, st, &m_ec);
+ if (!exists(fst) || !is_regular_file(fst)) {
+ errc error_kind =
+ is_directory(fst) ? errc::is_a_directory : errc::not_supported;
+ if (!m_ec)
+ m_ec = make_error_code(error_kind);
+ return err.report(m_ec);
+ }
+ // is_regular_file(p) == true
+ return static_cast<uintmax_t>(st.st_size);
+}
+
+uintmax_t __hard_link_count(const path& p, error_code* ec) {
+ ErrorHandler<uintmax_t> err("hard_link_count", ec, &p);
+
+ error_code m_ec;
+ StatT st;
+ detail::posix_stat(p, st, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ return static_cast<uintmax_t>(st.st_nlink);
+}
+
+bool __fs_is_empty(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("is_empty", ec, &p);
+
+ error_code m_ec;
+ StatT pst;
+ auto st = detail::posix_stat(p, pst, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ else if (!is_directory(st) && !is_regular_file(st))
+ return err.report(errc::not_supported);
+ else if (is_directory(st)) {
+ auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
+ if (ec && *ec)
+ return false;
+ return it == directory_iterator{};
+ } else if (is_regular_file(st))
+ return static_cast<uintmax_t>(pst.st_size) == 0;
+
+ _LIBCPP_UNREACHABLE();
+}
+
+static file_time_type __extract_last_write_time(const path& p, const StatT& st,
+ error_code* ec) {
+ using detail::fs_time;
+ ErrorHandler<file_time_type> err("last_write_time", ec, &p);
+
+ auto ts = detail::extract_mtime(st);
+ if (!fs_time::is_representable(ts))
+ return err.report(errc::value_too_large);
+
+ return fs_time::convert_from_timespec(ts);
+}
+
+file_time_type __last_write_time(const path& p, error_code* ec) {
+ using namespace chrono;
+ ErrorHandler<file_time_type> err("last_write_time", ec, &p);
+
+ error_code m_ec;
+ StatT st;
+ detail::posix_stat(p, st, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ return __extract_last_write_time(p, st, ec);
+}
+
+void __last_write_time(const path& p, file_time_type new_time, error_code* ec) {
+ using detail::fs_time;
+ ErrorHandler<void> err("last_write_time", ec, &p);
+
+ error_code m_ec;
+ array<TimeSpec, 2> tbuf;
+#if !defined(_LIBCPP_USE_UTIMENSAT)
+ // This implementation has a race condition between determining the
+ // last access time and attempting to set it to the same value using
+ // ::utimes
+ StatT st;
+ file_status fst = detail::posix_stat(p, st, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ tbuf[0] = detail::extract_atime(st);
+#else
+ tbuf[0].tv_sec = 0;
+ tbuf[0].tv_nsec = UTIME_OMIT;
+#endif
+ if (!fs_time::convert_to_timespec(tbuf[1], new_time))
+ return err.report(errc::value_too_large);
+
+ detail::set_file_times(p, tbuf, m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+}
+
+void __permissions(const path& p, perms prms, perm_options opts,
+ error_code* ec) {
+ ErrorHandler<void> err("permissions", ec, &p);
+
+ auto has_opt = [&](perm_options o) { return bool(o & opts); };
+ const bool resolve_symlinks = !has_opt(perm_options::nofollow);
+ const bool add_perms = has_opt(perm_options::add);
+ const bool remove_perms = has_opt(perm_options::remove);
+ _LIBCPP_ASSERT(
+ (add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
+ "One and only one of the perm_options constants replace, add, or remove "
+ "is present in opts");
+
+ bool set_sym_perms = false;
+ prms &= perms::mask;
+ if (!resolve_symlinks || (add_perms || remove_perms)) {
+ error_code m_ec;
+ file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
+ : detail::posix_lstat(p, &m_ec);
+ set_sym_perms = is_symlink(st);
+ if (m_ec)
+ return err.report(m_ec);
+ _LIBCPP_ASSERT(st.permissions() != perms::unknown,
+ "Permissions unexpectedly unknown");
+ if (add_perms)
+ prms |= st.permissions();
+ else if (remove_perms)
+ prms = st.permissions() & ~prms;
+ }
+ const auto real_perms = detail::posix_convert_perms(prms);
+
+#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
+ const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
+ if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
+ return err.report(capture_errno());
+ }
+#else
+ if (set_sym_perms)
+ return err.report(errc::operation_not_supported);
+ if (::chmod(p.c_str(), real_perms) == -1) {
+ return err.report(capture_errno());
+ }
+#endif
+}
+
+path __read_symlink(const path& p, error_code* ec) {
+ ErrorHandler<path> err("read_symlink", ec, &p);
+
+ char buff[PATH_MAX + 1];
+ error_code m_ec;
+ ::ssize_t ret;
+ if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
+ return err.report(capture_errno());
+ }
+ _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
+ _LIBCPP_ASSERT(ret > 0, "TODO");
+ buff[ret] = 0;
+ return {buff};
+}
+
+bool __remove(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("remove", ec, &p);
+ if (::remove(p.c_str()) == -1) {
+ if (errno != ENOENT)
+ err.report(capture_errno());
+ return false;
+ }
+ return true;
+}
+
+namespace {
+
+uintmax_t remove_all_impl(path const& p, error_code& ec) {
+ const auto npos = static_cast<uintmax_t>(-1);
+ const file_status st = __symlink_status(p, &ec);
+ if (ec)
+ return npos;
+ uintmax_t count = 1;
+ if (is_directory(st)) {
+ for (directory_iterator it(p, ec); !ec && it != directory_iterator();
+ it.increment(ec)) {
+ auto other_count = remove_all_impl(it->path(), ec);
+ if (ec)
+ return npos;
+ count += other_count;
+ }
+ if (ec)
+ return npos;
+ }
+ if (!__remove(p, &ec))
+ return npos;
+ return count;
+}
+
+} // end namespace
+
+uintmax_t __remove_all(const path& p, error_code* ec) {
+ ErrorHandler<uintmax_t> err("remove_all", ec, &p);
+
+ error_code mec;
+ auto count = remove_all_impl(p, mec);
+ if (mec) {
+ if (mec == errc::no_such_file_or_directory)
+ return 0;
+ return err.report(mec);
+ }
+ return count;
+}
+
+void __rename(const path& from, const path& to, error_code* ec) {
+ ErrorHandler<void> err("rename", ec, &from, &to);
+ if (::rename(from.c_str(), to.c_str()) == -1)
+ err.report(capture_errno());
+}
+
+void __resize_file(const path& p, uintmax_t size, error_code* ec) {
+ ErrorHandler<void> err("resize_file", ec, &p);
+ if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
+ return err.report(capture_errno());
+}
+
+space_info __space(const path& p, error_code* ec) {
+ ErrorHandler<void> err("space", ec, &p);
+ space_info si;
+ struct statvfs m_svfs = {};
+ if (::statvfs(p.c_str(), &m_svfs) == -1) {
+ err.report(capture_errno());
+ si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
+ return si;
+ }
+ // Multiply with overflow checking.
+ auto do_mult = [&](uintmax_t& out, uintmax_t other) {
+ out = other * m_svfs.f_frsize;
+ if (other == 0 || out / other != m_svfs.f_frsize)
+ out = static_cast<uintmax_t>(-1);
+ };
+ do_mult(si.capacity, m_svfs.f_blocks);
+ do_mult(si.free, m_svfs.f_bfree);
+ do_mult(si.available, m_svfs.f_bavail);
+ return si;
+}
+
+file_status __status(const path& p, error_code* ec) {
+ return detail::posix_stat(p, ec);
+}
+
+file_status __symlink_status(const path& p, error_code* ec) {
+ return detail::posix_lstat(p, ec);
+}
+
+path __temp_directory_path(error_code* ec) {
+ ErrorHandler<path> err("temp_directory_path", ec);
+
+ const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
+ const char* ret = nullptr;
+
+ for (auto& ep : env_paths)
+ if ((ret = getenv(ep)))
+ break;
+ if (ret == nullptr)
+ ret = "/tmp";
+
+ path p(ret);
+ error_code m_ec;
+ file_status st = detail::posix_stat(p, &m_ec);
+ if (!status_known(st))
+ return err.report(m_ec, "cannot access path \"%s\"", p);
+
+ if (!exists(st) || !is_directory(st))
+ return err.report(errc::not_a_directory, "path \"%s\" is not a directory",
+ p);
+
+ return p;
+}
+
+path __weakly_canonical(const path& p, error_code* ec) {
+ ErrorHandler<path> err("weakly_canonical", ec, &p);
+
+ if (p.empty())
+ return __canonical("", ec);
+
+ path result;
+ path tmp;
+ tmp.__reserve(p.native().size());
+ auto PP = PathParser::CreateEnd(p.native());
+ --PP;
+ vector<string_view_t> DNEParts;
+
+ while (PP.State != PathParser::PS_BeforeBegin) {
+ tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
+ error_code m_ec;
+ file_status st = __status(tmp, &m_ec);
+ if (!status_known(st)) {
+ return err.report(m_ec);
+ } else if (exists(st)) {
+ result = __canonical(tmp, ec);
+ break;
+ }
+ DNEParts.push_back(*PP);
+ --PP;
+ }
+ if (PP.State == PathParser::PS_BeforeBegin)
+ result = __canonical("", ec);
+ if (ec)
+ ec->clear();
+ if (DNEParts.empty())
+ return result;
+ for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
+ result /= *It;
+ return result.lexically_normal();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// path definitions
+///////////////////////////////////////////////////////////////////////////////
+
+constexpr path::value_type path::preferred_separator;
+
+path& path::replace_extension(path const& replacement) {
+ path p = extension();
+ if (not p.empty()) {
+ __pn_.erase(__pn_.size() - p.native().size());
+ }
+ if (!replacement.empty()) {
+ if (replacement.native()[0] != '.') {
+ __pn_ += ".";
+ }
+ __pn_.append(replacement.__pn_);
+ }
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// path.decompose
+
+string_view_t path::__root_name() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName)
+ return *PP;
+ return {};
+}
+
+string_view_t path::__root_directory() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName)
+ ++PP;
+ if (PP.State == PathParser::PS_InRootDir)
+ return *PP;
+ return {};
+}
+
+string_view_t path::__root_path_raw() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName) {
+ auto NextCh = PP.peek();
+ if (NextCh && *NextCh == '/') {
+ ++PP;
+ return createView(__pn_.data(), &PP.RawEntry.back());
+ }
+ return PP.RawEntry;
+ }
+ if (PP.State == PathParser::PS_InRootDir)
+ return *PP;
+ return {};
+}
+
+static bool ConsumeRootName(PathParser *PP) {
+ static_assert(PathParser::PS_BeforeBegin == 1 &&
+ PathParser::PS_InRootName == 2,
+ "Values for enums are incorrect");
+ while (PP->State <= PathParser::PS_InRootName)
+ ++(*PP);
+ return PP->State == PathParser::PS_AtEnd;
+}
+
+static bool ConsumeRootDir(PathParser* PP) {
+ static_assert(PathParser::PS_BeforeBegin == 1 &&
+ PathParser::PS_InRootName == 2 &&
+ PathParser::PS_InRootDir == 3, "Values for enums are incorrect");
+ while (PP->State <= PathParser::PS_InRootDir)
+ ++(*PP);
+ return PP->State == PathParser::PS_AtEnd;
+}
+
+string_view_t path::__relative_path() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (ConsumeRootDir(&PP))
+ return {};
+ return createView(PP.RawEntry.data(), &__pn_.back());
+}
+
+string_view_t path::__parent_path() const {
+ if (empty())
+ return {};
+ // Determine if we have a root path but not a relative path. In that case
+ // return *this.
+ {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (ConsumeRootDir(&PP))
+ return __pn_;
+ }
+ // Otherwise remove a single element from the end of the path, and return
+ // a string representing that path
+ {
+ auto PP = PathParser::CreateEnd(__pn_);
+ --PP;
+ if (PP.RawEntry.data() == __pn_.data())
+ return {};
+ --PP;
+ return createView(__pn_.data(), &PP.RawEntry.back());
+ }
+}
+
+string_view_t path::__filename() const {
+ if (empty())
+ return {};
+ {
+ PathParser PP = PathParser::CreateBegin(__pn_);
+ if (ConsumeRootDir(&PP))
+ return {};
+ }
+ return *(--PathParser::CreateEnd(__pn_));
+}
+
+string_view_t path::__stem() const {
+ return parser::separate_filename(__filename()).first;
+}
+
+string_view_t path::__extension() const {
+ return parser::separate_filename(__filename()).second;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.gen
+
+enum PathPartKind : unsigned char {
+ PK_None,
+ PK_RootSep,
+ PK_Filename,
+ PK_Dot,
+ PK_DotDot,
+ PK_TrailingSep
+};
+
+static PathPartKind ClassifyPathPart(string_view_t Part) {
+ if (Part.empty())
+ return PK_TrailingSep;
+ if (Part == ".")
+ return PK_Dot;
+ if (Part == "..")
+ return PK_DotDot;
+ if (Part == "/")
+ return PK_RootSep;
+ return PK_Filename;
+}
+
+path path::lexically_normal() const {
+ if (__pn_.empty())
+ return *this;
+
+ using PartKindPair = pair<string_view_t, PathPartKind>;
+ vector<PartKindPair> Parts;
+ // Guess as to how many elements the path has to avoid reallocating.
+ Parts.reserve(32);
+
+ // Track the total size of the parts as we collect them. This allows the
+ // resulting path to reserve the correct amount of memory.
+ size_t NewPathSize = 0;
+ auto AddPart = [&](PathPartKind K, string_view_t P) {
+ NewPathSize += P.size();
+ Parts.emplace_back(P, K);
+ };
+ auto LastPartKind = [&]() {
+ if (Parts.empty())
+ return PK_None;
+ return Parts.back().second;
+ };
+
+ bool MaybeNeedTrailingSep = false;
+ // Build a stack containing the remaining elements of the path, popping off
+ // elements which occur before a '..' entry.
+ for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
+ auto Part = *PP;
+ PathPartKind Kind = ClassifyPathPart(Part);
+ switch (Kind) {
+ case PK_Filename:
+ case PK_RootSep: {
+ // Add all non-dot and non-dot-dot elements to the stack of elements.
+ AddPart(Kind, Part);
+ MaybeNeedTrailingSep = false;
+ break;
+ }
+ case PK_DotDot: {
+ // Only push a ".." element if there are no elements preceding the "..",
+ // or if the preceding element is itself "..".
+ auto LastKind = LastPartKind();
+ if (LastKind == PK_Filename) {
+ NewPathSize -= Parts.back().first.size();
+ Parts.pop_back();
+ } else if (LastKind != PK_RootSep)
+ AddPart(PK_DotDot, "..");
+ MaybeNeedTrailingSep = LastKind == PK_Filename;
+ break;
+ }
+ case PK_Dot:
+ case PK_TrailingSep: {
+ MaybeNeedTrailingSep = true;
+ break;
+ }
+ case PK_None:
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+ // [fs.path.generic]p6.8: If the path is empty, add a dot.
+ if (Parts.empty())
+ return ".";
+
+ // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
+ // trailing directory-separator.
+ bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
+
+ path Result;
+ Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
+ for (auto& PK : Parts)
+ Result /= PK.first;
+
+ if (NeedTrailingSep)
+ Result /= "";
+
+ return Result;
+}
+
+static int DetermineLexicalElementCount(PathParser PP) {
+ int Count = 0;
+ for (; PP; ++PP) {
+ auto Elem = *PP;
+ if (Elem == "..")
+ --Count;
+ else if (Elem != "." && Elem != "")
+ ++Count;
+ }
+ return Count;
+}
+
+path path::lexically_relative(const path& base) const {
+ { // perform root-name/root-directory mismatch checks
+ auto PP = PathParser::CreateBegin(__pn_);
+ auto PPBase = PathParser::CreateBegin(base.__pn_);
+ auto CheckIterMismatchAtBase = [&]() {
+ return PP.State != PPBase.State &&
+ (PP.inRootPath() || PPBase.inRootPath());
+ };
+ if (PP.inRootName() && PPBase.inRootName()) {
+ if (*PP != *PPBase)
+ return {};
+ } else if (CheckIterMismatchAtBase())
+ return {};
+
+ if (PP.inRootPath())
+ ++PP;
+ if (PPBase.inRootPath())
+ ++PPBase;
+ if (CheckIterMismatchAtBase())
+ return {};
+ }
+
+ // Find the first mismatching element
+ auto PP = PathParser::CreateBegin(__pn_);
+ auto PPBase = PathParser::CreateBegin(base.__pn_);
+ while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) {
+ ++PP;
+ ++PPBase;
+ }
+
+ // If there is no mismatch, return ".".
+ if (!PP && !PPBase)
+ return ".";
+
+ // Otherwise, determine the number of elements, 'n', which are not dot or
+ // dot-dot minus the number of dot-dot elements.
+ int ElemCount = DetermineLexicalElementCount(PPBase);
+ if (ElemCount < 0)
+ return {};
+
+ // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
+ if (ElemCount == 0 && (PP.atEnd() || *PP == ""))
+ return ".";
+
+ // return a path constructed with 'n' dot-dot elements, followed by the
+ // elements of '*this' after the mismatch.
+ path Result;
+ // FIXME: Reserve enough room in Result that it won't have to re-allocate.
+ while (ElemCount--)
+ Result /= "..";
+ for (; PP; ++PP)
+ Result /= *PP;
+ return Result;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.comparisons
+static int CompareRootName(PathParser *LHS, PathParser *RHS) {
+ if (!LHS->inRootName() && !RHS->inRootName())
+ return 0;
+
+ auto GetRootName = [](PathParser *Parser) -> string_view_t {
+ return Parser->inRootName() ? **Parser : "";
+ };
+ int res = GetRootName(LHS).compare(GetRootName(RHS));
+ ConsumeRootName(LHS);
+ ConsumeRootName(RHS);
+ return res;
+}
+
+static int CompareRootDir(PathParser *LHS, PathParser *RHS) {
+ if (!LHS->inRootDir() && RHS->inRootDir())
+ return -1;
+ else if (LHS->inRootDir() && !RHS->inRootDir())
+ return 1;
+ else {
+ ConsumeRootDir(LHS);
+ ConsumeRootDir(RHS);
+ return 0;
+ }
+}
+
+static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) {
+ auto &LHS = *LHSPtr;
+ auto &RHS = *RHSPtr;
+
+ int res;
+ while (LHS && RHS) {
+ if ((res = (*LHS).compare(*RHS)) != 0)
+ return res;
+ ++LHS;
+ ++RHS;
+ }
+ return 0;
+}
+
+static int CompareEndState(PathParser *LHS, PathParser *RHS) {
+ if (LHS->atEnd() && !RHS->atEnd())
+ return -1;
+ else if (!LHS->atEnd() && RHS->atEnd())
+ return 1;
+ return 0;
+}
+
+int path::__compare(string_view_t __s) const {
+ auto LHS = PathParser::CreateBegin(__pn_);
+ auto RHS = PathParser::CreateBegin(__s);
+ int res;
+
+ if ((res = CompareRootName(&LHS, &RHS)) != 0)
+ return res;
+
+ if ((res = CompareRootDir(&LHS, &RHS)) != 0)
+ return res;
+
+ if ((res = CompareRelative(&LHS, &RHS)) != 0)
+ return res;
+
+ return CompareEndState(&LHS, &RHS);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.nonmembers
+size_t hash_value(const path& __p) noexcept {
+ auto PP = PathParser::CreateBegin(__p.native());
+ size_t hash_value = 0;
+ hash<string_view_t> hasher;
+ while (PP) {
+ hash_value = __hash_combine(hash_value, hasher(*PP));
+ ++PP;
+ }
+ return hash_value;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.itr
+path::iterator path::begin() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ iterator it;
+ it.__path_ptr_ = this;
+ it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
+ it.__entry_ = PP.RawEntry;
+ it.__stashed_elem_.__assign_view(*PP);
+ return it;
+}
+
+path::iterator path::end() const {
+ iterator it{};
+ it.__state_ = path::iterator::_AtEnd;
+ it.__path_ptr_ = this;
+ return it;
+}
+
+path::iterator& path::iterator::__increment() {
+ PathParser PP(__path_ptr_->native(), __entry_, __state_);
+ ++PP;
+ __state_ = static_cast<_ParserState>(PP.State);
+ __entry_ = PP.RawEntry;
+ __stashed_elem_.__assign_view(*PP);
+ return *this;
+}
+
+path::iterator& path::iterator::__decrement() {
+ PathParser PP(__path_ptr_->native(), __entry_, __state_);
+ --PP;
+ __state_ = static_cast<_ParserState>(PP.State);
+ __entry_ = PP.RawEntry;
+ __stashed_elem_.__assign_view(*PP);
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// directory entry definitions
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _LIBCPP_WIN32API
+error_code directory_entry::__do_refresh() noexcept {
+ __data_.__reset();
+ error_code failure_ec;
+
+ StatT full_st;
+ file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
+ if (!status_known(st)) {
+ __data_.__reset();
+ return failure_ec;
+ }
+
+ if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+ } else { // we have a symlink
+ __data_.__sym_perms_ = st.permissions();
+ // Get the information about the linked entity.
+ // Ignore errors from stat, since we don't want errors regarding symlink
+ // resolution to be reported to the user.
+ error_code ignored_ec;
+ st = detail::posix_stat(__p_, full_st, &ignored_ec);
+
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+
+ // If we failed to resolve the link, then only partially populate the
+ // cache.
+ if (!status_known(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
+ return error_code{};
+ }
+ // Otherwise, we resolved the link, potentially as not existing.
+ // That's OK.
+ __data_.__cache_type_ = directory_entry::_RefreshSymlink;
+ }
+
+ if (_VSTD_FS::is_regular_file(st))
+ __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
+
+ if (_VSTD_FS::exists(st)) {
+ __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
+
+ // Attempt to extract the mtime, and fail if it's not representable using
+ // file_time_type. For now we ignore the error, as we'll report it when
+ // the value is actually used.
+ error_code ignored_ec;
+ __data_.__write_time_ =
+ __extract_last_write_time(__p_, full_st, &ignored_ec);
+ }
+
+ return failure_ec;
+}
+#else
+error_code directory_entry::__do_refresh() noexcept {
+ __data_.__reset();
+ error_code failure_ec;
+
+ file_status st = _VSTD_FS::symlink_status(__p_, failure_ec);
+ if (!status_known(st)) {
+ __data_.__reset();
+ return failure_ec;
+ }
+
+ if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+ } else { // we have a symlink
+ __data_.__sym_perms_ = st.permissions();
+ // Get the information about the linked entity.
+ // Ignore errors from stat, since we don't want errors regarding symlink
+ // resolution to be reported to the user.
+ error_code ignored_ec;
+ st = _VSTD_FS::status(__p_, ignored_ec);
+
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+
+ // If we failed to resolve the link, then only partially populate the
+ // cache.
+ if (!status_known(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
+ return error_code{};
+ }
+ __data_.__cache_type_ = directory_entry::_RefreshSymlink;
+ }
+
+ // FIXME: This is currently broken, and the implementation only a placeholder.
+ // We need to cache last_write_time, file_size, and hard_link_count here before
+ // the implementation actually works.
+
+ return failure_ec;
+}
+#endif
+
+#ifndef _LIBAUTO_UNDEF_VSTD_FS
+#pragma pop_macro("_VSTD_FS")
+#else
+#undef _VSTD
+#undef _LIBAUTO_UNDEF_VSTD_FS
+#endif
+} // namespace android::hardware::automotive::filesystem
+/* clang-format on */
diff --git a/automotive/can/1.0/vts/functional/Android.bp b/automotive/can/1.0/vts/functional/Android.bp
index e3e770b..d020750 100644
--- a/automotive/can/1.0/vts/functional/Android.bp
+++ b/automotive/can/1.0/vts/functional/Android.bp
@@ -28,7 +28,10 @@
"android.hardware.automotive.can@vts-utils-lib",
"libgmock",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
cc_test {
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index 9f7cd3f..74d5122 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: ["vts-core"],
+ test_suites: ["vts"],
cflags: [
"-O0",
"-g",
diff --git a/automotive/evs/1.1/IEvsCamera.hal b/automotive/evs/1.1/IEvsCamera.hal
index 38e6c42..3e7ac2b 100644
--- a/automotive/evs/1.1/IEvsCamera.hal
+++ b/automotive/evs/1.1/IEvsCamera.hal
@@ -215,4 +215,22 @@
*/
setExtendedInfo_1_1(uint32_t opaqueIdentifier, vec<uint8_t> opaqueValue)
generates (EvsResult result);
+
+ /**
+ * Import external buffers to capture frames
+ *
+ * This API must be called with a physical camera device identifier.
+ *
+ * @param buffers A list of buffers allocated by the caller. EvsCamera
+ * will use these buffers to capture frames, in addition to
+ * other buffers already in its buffer pool.
+ * @return result EvsResult::OK if it succeeds to import buffers.
+ * EvsResult::UNDERLYING_SERVICE_ERROR if this is called
+ * for logical camera devices or EVS fails to import
+ * buffers.
+ * delta The amount of buffer pool size changes after importing
+ * given buffers.
+ */
+ importExternalBuffers(vec<BufferDesc> buffers)
+ generates (EvsResult result, int32_t delta);
};
diff --git a/automotive/evs/1.1/default/EvsCamera.cpp b/automotive/evs/1.1/default/EvsCamera.cpp
index 5196c95..0e69ed4 100644
--- a/automotive/evs/1.1/default/EvsCamera.cpp
+++ b/automotive/evs/1.1/default/EvsCamera.cpp
@@ -354,6 +354,14 @@
}
+Return<void>
+EvsCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& /* buffers */,
+ importExternalBuffers_cb _hidl_cb) {
+ ALOGW("%s is not implemented yet.", __FUNCTION__);
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
+ return {};
+}
+
bool EvsCamera::setAvailableFrames_Locked(unsigned bufferCount) {
if (bufferCount < 1) {
diff --git a/automotive/evs/1.1/default/EvsCamera.h b/automotive/evs/1.1/default/EvsCamera.h
index 0fa83b4..6163a34 100644
--- a/automotive/evs/1.1/default/EvsCamera.h
+++ b/automotive/evs/1.1/default/EvsCamera.h
@@ -82,6 +82,8 @@
const hidl_vec<uint8_t>& opaqueValue) override;
Return<void> getExtendedInfo_1_1(uint32_t opaqueIdentifier,
getExtendedInfo_1_1_cb _hidl_cb) override;
+ Return<void> importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) override;
static sp<EvsCamera> Create(const char *deviceName);
static sp<EvsCamera> Create(const char *deviceName,
diff --git a/automotive/evs/1.1/types.hal b/automotive/evs/1.1/types.hal
index b34e7e7..1f69f09 100644
--- a/automotive/evs/1.1/types.hal
+++ b/automotive/evs/1.1/types.hal
@@ -70,6 +70,9 @@
*/
int64_t timestamp;
+ /**
+ * Frame metadata. This is opaque to EVS manager.
+ */
vec<uint8_t> metadata;
};
diff --git a/automotive/evs/1.1/vts/functional/Android.bp b/automotive/evs/1.1/vts/functional/Android.bp
index 086a199..d61f0a8 100644
--- a/automotive/evs/1.1/vts/functional/Android.bp
+++ b/automotive/evs/1.1/vts/functional/Android.bp
@@ -38,7 +38,7 @@
"android.hardware.graphics.common@1.2",
"android.hardware.camera.device@3.2",
],
- test_suites: ["vts-core"],
+ test_suites: ["vts"],
cflags: [
"-O0",
"-g",
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 368a6d4..6a386c3 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -50,6 +50,8 @@
#include <system/camera_metadata.h>
#include <ui/DisplayConfig.h>
#include <ui/DisplayState.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
@@ -66,6 +68,7 @@
using ::android::sp;
using ::android::wp;
using ::android::hardware::camera::device::V3_2::Stream;
+using ::android::hardware::automotive::evs::V1_1::BufferDesc;
using ::android::hardware::automotive::evs::V1_0::DisplayDesc;
using ::android::hardware::automotive::evs::V1_0::DisplayState;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
@@ -2231,6 +2234,140 @@
/*
+ * CameraStreamExternalBuffering:
+ * This is same with CameraStreamBuffering except frame buffers are allocated by
+ * the test client and then imported by EVS framework.
+ */
+TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
+ LOG(INFO) << "Starting CameraStreamExternalBuffering test";
+
+ // Arbitrary constant (should be > 1 and less than crazy)
+ static const unsigned int kBuffersToHold = 6;
+
+ // Get the camera list
+ loadCameraList();
+
+ // Using null stream configuration makes EVS uses the default resolution and
+ // output format.
+ Stream nullCfg = {};
+
+ // Acquire the graphics buffer allocator
+ android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
+ const auto usage = GRALLOC_USAGE_HW_TEXTURE |
+ GRALLOC_USAGE_SW_READ_RARELY |
+ GRALLOC_USAGE_SW_WRITE_OFTEN;
+ const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
+ const auto width = 640;
+ const auto height = 360;
+
+ // Allocate buffers to use
+ hidl_vec<BufferDesc> buffers;
+ for (auto i = 0; i < kBuffersToHold; ++i) {
+ unsigned pixelsPerLine;
+ buffer_handle_t memHandle = nullptr;
+ android::status_t result = alloc.allocate(width,
+ height,
+ format,
+ 1,
+ usage,
+ &memHandle,
+ &pixelsPerLine,
+ 0,
+ "EvsApp");
+ if (result != android::NO_ERROR) {
+ LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
+ } else {
+ BufferDesc buf;
+ AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<AHardwareBuffer_Desc *>(&buf.buffer.description);
+ pDesc->width = width;
+ pDesc->height = height;
+ pDesc->layers = 1;
+ pDesc->format = format;
+ pDesc->usage = usage;
+ pDesc->stride = pixelsPerLine;
+ buf.buffer.nativeHandle = memHandle;
+ buf.bufferId = i; // Unique number to identify this buffer
+ buffers[i] = buf;
+ }
+ }
+
+ // Test each reported camera
+ for (auto&& cam: cameraInfo) {
+ bool isLogicalCam = false;
+ getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
+
+ sp<IEvsCamera_1_1> pCam =
+ IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
+ .withDefault(nullptr);
+ ASSERT_NE(pCam, nullptr);
+
+ // Store a camera handle for a clean-up
+ activeCameras.push_back(pCam);
+
+ // Request to import buffers
+ EvsResult result = EvsResult::OK;
+ int delta = 0;
+ pCam->importExternalBuffers(buffers,
+ [&] (auto _result, auto _delta) {
+ result = _result;
+ delta = _delta;
+ });
+ if (isLogicalCam) {
+ EXPECT_EQ(result, EvsResult::UNDERLYING_SERVICE_ERROR);
+ continue;
+ }
+
+ EXPECT_EQ(result, EvsResult::OK);
+ EXPECT_GE(delta, 0);
+
+ // Set up a frame receiver object which will fire up its own thread.
+ sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
+ nullptr,
+ FrameHandler::eNoAutoReturn);
+
+ // Start the camera's video stream
+ bool startResult = frameHandler->startStream();
+ ASSERT_TRUE(startResult);
+
+ // Check that the video stream stalls once we've gotten exactly the number of buffers
+ // we requested since we told the frameHandler not to return them.
+ sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case
+ unsigned framesReceived = 0;
+ frameHandler->getFramesCounters(&framesReceived, nullptr);
+ ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+
+
+ // Give back one buffer
+ bool didReturnBuffer = frameHandler->returnHeldBuffer();
+ EXPECT_TRUE(didReturnBuffer);
+
+ // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
+ // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+ usleep(110 * kMillisecondsToMicroseconds);
+ frameHandler->getFramesCounters(&framesReceived, nullptr);
+ EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
+
+ // Even when the camera pointer goes out of scope, the FrameHandler object will
+ // keep the stream alive unless we tell it to shutdown.
+ // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+ // we have to break that cycle in order for either of them to get cleaned up.
+ frameHandler->shutdown();
+
+ // Explicitly release the camera
+ pEnumerator->closeCamera(pCam);
+ activeCameras.clear();
+ }
+
+ // Release buffers
+ for (auto& b : buffers) {
+ alloc.free(b.buffer.nativeHandle);
+ }
+ buffers.resize(0);
+}
+
+
+/*
* UltrasonicsArrayOpenClean:
* Opens each ultrasonics arrays reported by the enumerator and then explicitly closes it via a
* call to closeUltrasonicsArray. Then repeats the test to ensure all ultrasonics arrays
diff --git a/automotive/occupant_awareness/aidl/Android.bp b/automotive/occupant_awareness/aidl/Android.bp
index face235..4127f33 100644
--- a/automotive/occupant_awareness/aidl/Android.bp
+++ b/automotive/occupant_awareness/aidl/Android.bp
@@ -15,4 +15,5 @@
},
},
},
+ versions: ["1"],
}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/.hash b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/.hash
new file mode 100644
index 0000000..6786231
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/.hash
@@ -0,0 +1 @@
+3614b1c47ed7be85c1e77554e7f04966cf35b465
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl
new file mode 100644
index 0000000..6e40d79
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="byte") @VintfStability
+enum ConfidenceLevel {
+ NONE = 0,
+ LOW = 1,
+ HIGH = 2,
+ MAX = 3,
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl
new file mode 100644
index 0000000..51d2149
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable DriverMonitoringDetection {
+ android.hardware.automotive.occupant_awareness.ConfidenceLevel confidenceScore;
+ boolean isLookingOnRoad;
+ long gazeDurationMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/GazeDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/GazeDetection.aidl
new file mode 100644
index 0000000..5ce14df
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/GazeDetection.aidl
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable GazeDetection {
+ android.hardware.automotive.occupant_awareness.ConfidenceLevel gazeConfidence;
+ double[] headPosition;
+ double[] headAngleUnitVector;
+ double[] gazeAngleUnitVector;
+ android.hardware.automotive.occupant_awareness.VehicleRegion gazeTarget;
+ String customGazeTarget;
+ long timeOnTargetMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl
new file mode 100644
index 0000000..7faff00
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+interface IOccupantAwareness {
+ android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus startDetection();
+ android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus stopDetection();
+ int getCapabilityForRole(in android.hardware.automotive.occupant_awareness.Role occupantRole);
+ android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus getState(in android.hardware.automotive.occupant_awareness.Role occupantRole, in int detectionCapability);
+ void setCallback(in android.hardware.automotive.occupant_awareness.IOccupantAwarenessClientCallback callback);
+ void getLatestDetection(out android.hardware.automotive.occupant_awareness.OccupantDetections detections);
+ const int CAP_NONE = 0;
+ const int CAP_PRESENCE_DETECTION = 1;
+ const int CAP_GAZE_DETECTION = 2;
+ const int CAP_DRIVER_MONITORING_DETECTION = 4;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl
new file mode 100644
index 0000000..31b8220
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+interface IOccupantAwarenessClientCallback {
+ oneway void onSystemStatusChanged(in int detectionFlags, in android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus status);
+ oneway void onDetectionEvent(in android.hardware.automotive.occupant_awareness.OccupantDetections detections);
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl
new file mode 100644
index 0000000..26371c9
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="byte") @VintfStability
+enum OccupantAwarenessStatus {
+ READY = 0,
+ NOT_SUPPORTED = 1,
+ NOT_INITIALIZED = 2,
+ FAILURE = 3,
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl
new file mode 100644
index 0000000..42b1095
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable OccupantDetection {
+ android.hardware.automotive.occupant_awareness.Role role;
+ android.hardware.automotive.occupant_awareness.PresenceDetection[] presenceData;
+ android.hardware.automotive.occupant_awareness.GazeDetection[] gazeData;
+ android.hardware.automotive.occupant_awareness.DriverMonitoringDetection[] attentionData;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl
new file mode 100644
index 0000000..9bcad6b
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable OccupantDetections {
+ long timeStampMillis;
+ android.hardware.automotive.occupant_awareness.OccupantDetection[] detections;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl
new file mode 100644
index 0000000..dd6c5c8
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable PresenceDetection {
+ boolean isOccupantDetected;
+ long detectionDurationMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/Role.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/Role.aidl
new file mode 100644
index 0000000..7b2b907
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/Role.aidl
@@ -0,0 +1,35 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="int") @VintfStability
+enum Role {
+ INVALID = 0,
+ UNKNOWN = 1,
+ FRONT_PASSENGER = 2,
+ DRIVER = 4,
+ ROW_2_PASSENGER_LEFT = 8,
+ ROW_2_PASSENGER_CENTER = 16,
+ ROW_2_PASSENGER_RIGHT = 32,
+ ROW_3_PASSENGER_LEFT = 64,
+ ROW_3_PASSENGER_CENTER = 128,
+ ROW_3_PASSENGER_RIGHT = 256,
+ FRONT_OCCUPANTS = 6,
+ ROW_2_OCCUPANTS = 56,
+ ROW_3_OCCUPANTS = 448,
+ ALL_OCCUPANTS = 511,
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl
new file mode 100644
index 0000000..f96d950
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="int") @VintfStability
+enum VehicleRegion {
+ UNKNOWN = 0,
+ INSTRUMENT_CLUSTER = 1,
+ REAR_VIEW_MIRROR = 2,
+ LEFT_SIDE_MIRROR = 3,
+ RIGHT_SIDE_MIRROR = 4,
+ FORWARD_ROADWAY = 5,
+ LEFT_ROADWAY = 6,
+ RIGHT_ROADWAY = 7,
+ HEAD_UNIT_DISPLAY = 8,
+ CUSTOM_TARGET = 200,
+}
diff --git a/automotive/occupant_awareness/aidl/vts/functional/Android.bp b/automotive/occupant_awareness/aidl/vts/functional/Android.bp
index 1256b69..514b0af 100644
--- a/automotive/occupant_awareness/aidl/vts/functional/Android.bp
+++ b/automotive/occupant_awareness/aidl/vts/functional/Android.bp
@@ -12,6 +12,6 @@
"android.hardware.automotive.occupant_awareness-cpp",
],
test_suites: [
- "vts-core",
+ "vts",
],
}
diff --git a/automotive/sv/1.0/vts/functional/Android.bp b/automotive/sv/1.0/vts/functional/Android.bp
index 0e5d3df..d5d72a6 100644
--- a/automotive/sv/1.0/vts/functional/Android.bp
+++ b/automotive/sv/1.0/vts/functional/Android.bp
@@ -33,7 +33,7 @@
"android.hidl.memory@1.0",
"libhidlmemory",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
cflags: [
"-O0",
"-g",
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index e529675..872b35b 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -75,7 +75,10 @@
],
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["impl"],
- whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+ whole_static_libs: [
+ "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
+ "android.hardware.automotive.vehicle@2.0-manager-lib",
+ ],
shared_libs: [
"libbase",
"libjsoncpp",
@@ -87,6 +90,16 @@
],
}
+// Library used to emulate User HAL behavior through lshal debug requests.
+cc_library_static {
+ name: "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
+ vendor: true,
+ defaults: ["vhal_v2_0_defaults"],
+ srcs: [
+ "impl/vhal_v2_0/EmulatedUserHal.cpp",
+ ],
+}
+
cc_test {
name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests",
vendor: true,
@@ -125,6 +138,9 @@
cc_binary {
name: "android.hardware.automotive.vehicle@2.0-service",
defaults: ["vhal_v2_0_defaults"],
+ vintf_fragments: [
+ "android.hardware.automotive.vehicle@2.0-service.xml",
+ ],
init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"],
vendor: true,
relative_install_path: "hw",
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.xml b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.xml
new file mode 100644
index 0000000..660b03d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.automotive.vehicle</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IVehicle</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index 5bebd1e..b09e9bf 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -27,14 +27,11 @@
#include <android/log.h>
#include <hwbinder/IPCThreadState.h>
-
+#include <private/android_filesystem_config.h>
#include <utils/SystemClock.h>
#include "VehicleUtils.h"
-// TODO: figure out how to include private/android_filesystem_config.h instead...
-#define AID_ROOT 0 /* traditional unix root user */
-
namespace android {
namespace hardware {
namespace automotive {
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 ea75986..b8a606a 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
@@ -79,8 +79,6 @@
constexpr int WHEEL_FRONT_RIGHT = (int)VehicleAreaWheel::RIGHT_FRONT;
constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR;
constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR;
-constexpr int INITIAL_USER_INFO = (int)VehicleProperty::INITIAL_USER_INFO;
-constexpr int SWITCH_USER = (int)VehicleProperty::SWITCH_USER;
/**
* This property is used for test purpose to generate fake events. Here is the test package that
@@ -439,6 +437,16 @@
{.config =
{
+ .prop = toInt(VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .configArray = {(int)VehicleUnit::KILOPASCAL, (int)VehicleUnit::PSI,
+ (int)VehicleUnit::BAR},
+ },
+ .initialValue = {.int32Values = {toInt(VehicleUnit::PSI)}}},
+
+ {.config =
+ {
.prop = toInt(VehicleProperty::CURRENT_GEAR),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -1028,6 +1036,14 @@
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
+ {
+ .config =
+ {
+ .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ },
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
new file mode 100644
index 0000000..c49fadc
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "EmulatedUserHal"
+
+#include <cutils/log.h>
+#include <utils/SystemClock.h>
+
+#include "EmulatedUserHal.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+constexpr int INITIAL_USER_INFO = static_cast<int>(VehicleProperty::INITIAL_USER_INFO);
+constexpr int SWITCH_USER = static_cast<int>(VehicleProperty::SWITCH_USER);
+
+bool EmulatedUserHal::isSupported(int32_t prop) {
+ switch (prop) {
+ case INITIAL_USER_INFO:
+ case SWITCH_USER:
+ return true;
+ default:
+ return false;
+ }
+}
+
+android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty(
+ const VehiclePropValue& value) {
+ ALOGV("onSetProperty(): %s", toString(value).c_str());
+
+ switch (value.prop) {
+ case INITIAL_USER_INFO:
+ return onSetInitialUserInfoResponse(value);
+ case SWITCH_USER:
+ return onSetSwitchUserResponse(value);
+ default:
+ return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+ << "Unsupported property: " << toString(value);
+ }
+}
+
+android::base::Result<std::unique_ptr<VehiclePropValue>>
+EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) {
+ if (value.value.int32Values.size() == 0) {
+ ALOGE("set(INITIAL_USER_INFO): no int32values, ignoring it: %s", toString(value).c_str());
+ return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+ << "no int32values on " << toString(value);
+ }
+
+ if (value.areaId != 0) {
+ ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", toString(value).c_str());
+ mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
+ return {};
+ }
+
+ ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str());
+
+ int32_t requestId = value.value.int32Values[0];
+ if (mInitialUserResponseFromCmd != nullptr) {
+ ALOGI("replying INITIAL_USER_INFO with lshal value: %s",
+ toString(*mInitialUserResponseFromCmd).c_str());
+ return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), requestId);
+ }
+
+ // Returns default response
+ auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
+ updatedValue->prop = INITIAL_USER_INFO;
+ updatedValue->timestamp = elapsedRealtimeNano();
+ updatedValue->value.int32Values.resize(2);
+ updatedValue->value.int32Values[0] = requestId;
+ updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
+
+ ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s",
+ toString(*updatedValue).c_str());
+
+ return updatedValue;
+}
+
+android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse(
+ const VehiclePropValue& value) {
+ if (value.value.int32Values.size() == 0) {
+ ALOGE("set(SWITCH_USER): no int32values, ignoring it: %s", toString(value).c_str());
+ return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+ << "no int32values on " << toString(value);
+ }
+
+ if (value.areaId != 0) {
+ ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str());
+ mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value));
+ return {};
+ }
+ ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str());
+
+ int32_t requestId = value.value.int32Values[0];
+ if (mSwitchUserResponseFromCmd != nullptr) {
+ ALOGI("replying SWITCH_USER with lshal value: %s",
+ toString(*mSwitchUserResponseFromCmd).c_str());
+ return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), requestId);
+ }
+
+ // Returns default response
+ auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
+ updatedValue->prop = SWITCH_USER;
+ updatedValue->timestamp = elapsedRealtimeNano();
+ updatedValue->value.int32Values.resize(3);
+ updatedValue->value.int32Values[0] = requestId;
+ updatedValue->value.int32Values[1] = (int32_t)SwitchUserMessageType::VEHICLE_RESPONSE;
+ updatedValue->value.int32Values[2] = (int32_t)SwitchUserStatus::SUCCESS;
+
+ ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s",
+ toString(*updatedValue).c_str());
+
+ return updatedValue;
+}
+
+android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
+ std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
+ switch (response->areaId) {
+ case 1:
+ ALOGD("returning response with right request id");
+ response->value.int32Values[0] = requestId;
+ break;
+ case 2:
+ ALOGD("returning response with wrong request id");
+ response->value.int32Values[0] = -requestId;
+ break;
+ case 3:
+ ALOGD("not generating a property change event because of lshal prop: %s",
+ toString(*response).c_str());
+ return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
+ << "not generating a property change event because of lshal prop: "
+ << toString(*response);
+ default:
+ ALOGE("invalid action on lshal response: %s", toString(*response).c_str());
+ return android::base::Error(static_cast<int>(StatusCode::INTERNAL_ERROR))
+ << "invalid action on lshal response: " << toString(*response);
+ }
+
+ ALOGD("updating property to: %s", toString(*response).c_str());
+
+ return response;
+}
+
+void EmulatedUserHal::showDumpHelp(int fd) {
+ dprintf(fd, "%s: dumps state used for user management\n", kUserHalDumpOption);
+}
+
+void EmulatedUserHal::dump(int fd, std::string indent) {
+ if (mInitialUserResponseFromCmd != nullptr) {
+ dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(),
+ toString(*mInitialUserResponseFromCmd).c_str());
+ } else {
+ dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str());
+ }
+ if (mSwitchUserResponseFromCmd != nullptr) {
+ dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(),
+ toString(*mSwitchUserResponseFromCmd).c_str());
+ } else {
+ dprintf(fd, "%sNo SwitchUser response\n", indent.c_str());
+ }
+}
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
new file mode 100644
index 0000000..b25efcb
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
+
+#include <android-base/result.h>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+constexpr char kUserHalDumpOption[] = "--user-hal";
+
+/**
+ * Class used to emulate User HAL behavior through lshal debug requests.
+ */
+class EmulatedUserHal {
+ public:
+ EmulatedUserHal() {}
+
+ ~EmulatedUserHal() = default;
+
+ /**
+ * Checks if the emulator can handle the property.
+ */
+ bool isSupported(int32_t prop);
+
+ /**
+ * Lets the emulator handle the property.
+ *
+ * @return updated property and StatusCode
+ */
+ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetProperty(
+ const VehiclePropValue& value);
+
+ /**
+ * Shows the User HAL emulation help.
+ */
+ void showDumpHelp(int fd);
+
+ /**
+ * Dump its contents.
+ */
+ void dump(int fd, std::string indent);
+
+ private:
+ /**
+ * 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)
+ *
+ */
+ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetInitialUserInfoResponse(
+ const VehiclePropValue& value);
+
+ /**
+ * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage.
+ */
+ android::base::Result<std::unique_ptr<VehiclePropValue>> onSetSwitchUserResponse(
+ const VehiclePropValue& value);
+
+ android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse(
+ std::unique_ptr<VehiclePropValue> response, int32_t requestId);
+
+ std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
+ std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
+};
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
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 ce7dc65..7f9362f 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
@@ -38,9 +38,6 @@
class EmulatedPassthroughConnector : public PassthroughConnector {
public:
bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
- private:
- void dumpUserHal(int fd, std::string indent);
};
bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle,
@@ -50,12 +47,12 @@
if (options.size() > 0) {
if (options[0] == "--help") {
dprintf(fd, "Emulator-specific usage:\n");
- dprintf(fd, "--user-hal: dumps state used for user management \n");
+ mEmulatedUserHal.showDumpHelp(fd);
dprintf(fd, "\n");
// Include caller's help options
return true;
- } else if (options[0] == "--user-hal") {
- dumpUserHal(fd, "");
+ } else if (options[0] == kUserHalDumpOption) {
+ mEmulatedUserHal.dump(fd, "");
return false;
} else {
@@ -65,27 +62,12 @@
}
dprintf(fd, "Emulator-specific state:\n");
- dumpUserHal(fd, " ");
+ mEmulatedUserHal.dump(fd, " ");
dprintf(fd, "\n");
return true;
}
-void EmulatedPassthroughConnector::dumpUserHal(int fd, std::string indent) {
- if (mInitialUserResponseFromCmd != nullptr) {
- dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(),
- toString(*mInitialUserResponseFromCmd).c_str());
- } else {
- dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str());
- }
- if (mSwitchUserResponseFromCmd != nullptr) {
- dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(),
- toString(*mSwitchUserResponseFromCmd).c_str());
- } else {
- dprintf(fd, "%sNo SwitchUser response\n", indent.c_str());
- }
-}
-
PassthroughConnectorPtr makeEmulatedPassthroughConnector() {
return std::make_unique<EmulatedPassthroughConnector>();
}
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 e99de60..02c00c1 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
@@ -16,8 +16,12 @@
#define LOG_TAG "DefaultVehicleHal_v2_0"
#include <android-base/macros.h>
+#include <android-base/properties.h>
#include <android/log.h>
+#include <dirent.h>
#include <sys/system_properties.h>
+#include <fstream>
+#include <regex>
#include "EmulatedVehicleHal.h"
#include "JsonFakeValueGenerator.h"
@@ -101,6 +105,30 @@
mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
this, std::placeholders::_1,
std::placeholders::_2));
+
+ mInitVhalValueOverride =
+ android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false);
+ if (mInitVhalValueOverride) {
+ getAllPropertiesOverride();
+ }
+}
+
+void EmulatedVehicleHal::getAllPropertiesOverride() {
+ if (auto dir = opendir("/vendor/etc/vhaloverride/")) {
+ std::regex reg_json(".*[.]json", std::regex::icase);
+ while (auto f = readdir(dir)) {
+ if (!regex_match(f->d_name, reg_json)) {
+ continue;
+ }
+ std::string file = "/vendor/etc/vhaloverride/" + std::string(f->d_name);
+ JsonFakeValueGenerator tmpGenerator(file);
+
+ std::vector<VehiclePropValue> propvalues = tmpGenerator.getAllEvents();
+ mVehiclePropertiesOverride.insert(std::end(mVehiclePropertiesOverride),
+ std::begin(propvalues), std::end(propvalues));
+ }
+ closedir(dir);
+ }
}
VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
@@ -275,6 +303,13 @@
}
} else {
prop.value = it.initialValue;
+ if (mInitVhalValueOverride) {
+ for (auto& itOverride : mVehiclePropertiesOverride) {
+ if (itOverride.prop == cfg.prop) {
+ prop.value = itOverride.value;
+ }
+ }
+ }
}
mPropStore->writeValue(prop, shouldUpdateStatus);
}
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 dc05145..cba4b8a 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
@@ -62,6 +62,7 @@
// Methods from EmulatedVehicleHalIface
bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
std::vector<VehiclePropValue> getAllProperties() const override;
+ void getAllPropertiesOverride();
private:
constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
@@ -87,6 +88,8 @@
RecurrentTimer mRecurrentTimer;
VehicleHalClient* mVehicleClient;
bool mInEmulator;
+ bool mInitVhalValueOverride;
+ std::vector<VehiclePropValue> mVehiclePropertiesOverride;
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index 8677f83..890eb33 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -48,6 +48,22 @@
mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
}
+JsonFakeValueGenerator::JsonFakeValueGenerator(std::string path) {
+ std::ifstream ifs(path);
+ if (!ifs) {
+ ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
+ }
+ mGenCfg = {
+ .index = 0,
+ .events = parseFakeValueJson(ifs),
+ };
+ mNumOfIterations = mGenCfg.events.size();
+}
+
+std::vector<VehiclePropValue> JsonFakeValueGenerator::getAllEvents() {
+ return mGenCfg.events;
+}
+
VehiclePropValue JsonFakeValueGenerator::nextEvent() {
VehiclePropValue generatedValue;
if (!hasNext()) {
@@ -109,6 +125,7 @@
Json::Value rawEventValue = rawEvent["value"];
auto& value = event.value;
+ int32_t count;
switch (getPropType(event.prop)) {
case VehiclePropertyType::BOOLEAN:
case VehiclePropertyType::INT32:
@@ -126,6 +143,13 @@
case VehiclePropertyType::STRING:
value.stringValue = rawEventValue.asString();
break;
+ case VehiclePropertyType::INT32_VEC:
+ value.int32Values.resize(rawEventValue.size());
+ count = 0;
+ for (auto& it : rawEventValue) {
+ value.int32Values[count++] = it.asInt();
+ }
+ break;
case VehiclePropertyType::MIXED:
copyMixedValueJson(value, rawEventValue);
if (isDiagnosticProperty(event.prop)) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index 70575f7..dc8ff66 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -41,9 +41,12 @@
public:
JsonFakeValueGenerator(const VehiclePropValue& request);
+ JsonFakeValueGenerator(std::string path);
+
~JsonFakeValueGenerator() = default;
VehiclePropValue nextEvent();
+ std::vector<VehiclePropValue> getAllEvents();
bool hasNext();
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
index 70e39eb..ad5096e 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -181,6 +181,23 @@
}
StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
+ if (mEmulatedUserHal.isSupported(value.prop)) {
+ LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
+
+ const auto& ret = mEmulatedUserHal.onSetProperty(value);
+ if (!ret.ok()) {
+ LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
+ return StatusCode(ret.error().code());
+ }
+ auto updatedValue = ret.value().get();
+ if (updatedValue != nullptr) {
+ LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
+ << toString(*updatedValue);
+ onPropertyValueFromCar(*updatedValue, updateStatus);
+ }
+ return StatusCode::OK;
+ }
+
// Some properties need to be treated non-trivially
switch (value.prop) {
case kGenerateFakeDataControllingProperty:
@@ -245,10 +262,6 @@
break;
}
break;
- case INITIAL_USER_INFO:
- return onSetInitialUserInfoResponse(value, updateStatus);
- case SWITCH_USER:
- return onSetSwitchUserResponse(value, updateStatus);
default:
break;
}
@@ -262,165 +275,4 @@
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::onSetInitialUserInfoResponse(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/150409377): 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;
-}
-
-/**
- * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage.
- */
-StatusCode VehicleHalServer::onSetSwitchUserResponse(const VehiclePropValue& value,
- bool updateStatus) {
- if (value.value.int32Values.size() == 0) {
- LOG(ERROR) << "set(SWITCH_USER): no int32values, ignoring it: " << toString(value);
- return StatusCode::INVALID_ARG;
- }
-
- if (value.areaId != 0) {
- LOG(INFO) << "set(SWITCH_USER) called from lshal; storing it: " << toString(value);
- mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value));
- return StatusCode::OK;
- }
- LOG(INFO) << "set(SWITCH_USER) 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 = SWITCH_USER;
- updatedValue->timestamp = elapsedRealtimeNano();
-
- if (mSwitchUserResponseFromCmd == nullptr) {
- updatedValue->value.int32Values.resize(3);
- updatedValue->value.int32Values[0] = requestId;
- updatedValue->value.int32Values[1] = (int32_t)SwitchUserMessageType::VEHICLE_RESPONSE;
- updatedValue->value.int32Values[2] = (int32_t)SwitchUserStatus::SUCCESS;
- LOG(INFO) << "no lshal response; returning VEHICLE_RESPONSE / SUCCESS: "
- << toString(*updatedValue);
- onPropertyValueFromCar(*updatedValue, updateStatus);
- return StatusCode::OK;
- }
-
- // mSwitchUserResponseFromCmd is used for just one request
- std::unique_ptr<VehiclePropValue> response = std::move(mSwitchUserResponseFromCmd);
-
- // TODO(b/150409377): move code below to a local function like sendUserHalResponse(),
- // as it's the same for all (like onSetInitialUserInfoResponse)
-
- 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
index 20e094a..2841fbe 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -19,6 +19,7 @@
#include <vhal_v2_0/VehicleObjectPool.h>
#include <vhal_v2_0/VehicleServer.h>
+#include "EmulatedUserHal.h"
#include "GeneratorHub.h"
namespace android::hardware::automotive::vehicle::V2_0::impl {
@@ -53,15 +54,10 @@
VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
int32_t targetDisplay);
- StatusCode onSetInitialUserInfoResponse(const VehiclePropValue& value, bool updateStatus);
- StatusCode onSetSwitchUserResponse(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;
- std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
+ EmulatedUserHal mEmulatedUserHal;
private:
GeneratorHub mGeneratorHub{
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
index 2eedecd..31ba8ab 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
@@ -27,29 +27,16 @@
"-Wall",
"-Werror",
],
- srcs: ["VehicleHalProto.proto"]
+ srcs: ["VehicleHalProto.proto"],
}
-cc_library_static {
- name: "android.hardware.automotive.vehicle@2.0-grpc",
- vendor: true,
- include_dirs: [
- "external/protobuf/src",
+filegroup {
+ name: "vhal-proto-src",
+ visibility: [
+ "//device/google/trout/hal/vehicle/2.0:__subpackages__",
],
- generated_headers: [
- "DefaultVehicleHalProtoStub_h",
- ],
- export_generated_headers: [
- "DefaultVehicleHalProtoStub_h",
- ],
- generated_sources: [
- "DefaultVehicleHalProtoStub_cc",
- ],
- shared_libs: [
- "libgrpc++_unsecure",
- ],
- cflags: [
- "-Wno-unused-parameter"
+ srcs: [
+ "VehicleHalProto.proto",
],
}
@@ -62,13 +49,10 @@
cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
srcs: [
"VehicleHalProto.proto",
- "VehicleServer.proto",
],
out: [
"VehicleHalProto.pb.h",
"VehicleHalProto.grpc.pb.h",
- "VehicleServer.pb.h",
- "VehicleServer.grpc.pb.h",
],
}
@@ -81,12 +65,9 @@
cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
srcs: [
"VehicleHalProto.proto",
- "VehicleServer.proto",
],
out: [
"VehicleHalProto.pb.cc",
"VehicleHalProto.grpc.pb.cc",
- "VehicleServer.pb.cc",
- "VehicleServer.grpc.pb.cc",
],
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto
deleted file mode 100644
index 6f71d65..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto
+++ /dev/null
@@ -1,57 +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.
- */
-
-syntax = "proto3";
-
-package vhal_proto;
-
-import "google/protobuf/empty.proto";
-import "VehicleHalProto.proto";
-
-// correspond to StatusCode defined in types.hal
-enum VehicleHalStatusCode {
- OK = 0;
- TRY_AGAIN = 1;
- INVALID_ARG = 2;
- NOT_AVAILABLE = 3;
- ACCESS_DENIED = 4;
- INTERNAL_ERROR = 5;
-}
-
-message VehicleHalCallStatus {
- VehicleHalStatusCode status_code = 1;
-}
-
-message WrappedVehiclePropValue {
- VehiclePropValue value = 1;
- // An indicator on whether we should update the status of the property
- // - true: if the value is generated by (emulated/real) car, or;
- // if the value is injected to 'fake' a on car event (for debugging purpose)
- // - false: if the value is set by VHal (public interface), since Android
- // cannot change status of property on a real car
- bool update_status = 2;
-}
-
-service VehicleServer {
- rpc GetAllPropertyConfig(google.protobuf.Empty) returns (stream VehiclePropConfig) {}
-
- // Change the property value of the vehicle
- rpc SetProperty(WrappedVehiclePropValue) returns (VehicleHalCallStatus) {}
-
- // Start a vehicle property value stream
- rpc StartPropertyValuesStream(google.protobuf.Empty) returns (stream WrappedVehiclePropValue) {}
-}
-
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 23f9135..ee34e42 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -606,8 +606,23 @@
/**
* Tire pressure
*
- * min/max value indicates tire pressure sensor range. Each tire will have a separate min/max
- * value denoted by its areaConfig.areaId.
+ * Each tires is identified by its areaConfig.areaId config and their
+ * minFloatValue/maxFloatValue are used to store OEM recommended pressure
+ * range.
+ * The Min value in the areaConfig data represents the lower bound of
+ * the recommended tire pressure.
+ * The Max value in the areaConfig data represents the upper bound of
+ * the recommended tire pressure.
+ * For example:
+ * The following areaConfig indicates the recommended tire pressure
+ * of left_front tire is from 200.0 KILOPASCAL to 240.0 KILOPASCAL.
+ * .areaConfigs = {
+ * VehicleAreaConfig {
+ * .areaId = VehicleAreaWheel::LEFT_FRONT,
+ * .minFloatValue = 200.0,
+ * .maxFloatValue = 240.0,
+ * }
+ * },
*
* @change_mode VehiclePropertyChangeMode:CONTINUOUS
* @access VehiclePropertyAccess:READ
@@ -786,7 +801,8 @@
/*
* HVAC Properties
*
- * Additional rules for mapping a zoned HVAC property to AreaIDs:
+ * Additional rules for mapping a zoned HVAC property (except
+ * HVAC_MAX_DEFROST_ON) to AreaIDs:
* - Every seat in VehicleAreaSeat that is available in the car, must be
* part of an AreaID in the AreaID array.
*
@@ -919,6 +935,11 @@
* possible. Any parameters modified as a side effect of turning on/off
* the MAX DEFROST parameter shall generate onPropertyEvent() callbacks to
* the VHAL.
+ * The AreaIDs for HVAC_MAX_DEFROST_ON indicate MAX DEFROST can be controlled
+ * in the area.
+ * For example:
+ * areaConfig.areaId = {ROW_1_LEFT | ROW_1_RIGHT} indicates HVAC_MAX_DEFROST_ON
+ * only can be controlled for the front rows.
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ_WRITE
@@ -2646,9 +2667,9 @@
* If the request succeeded and Android has 3 users (0, 10, 11), the response would be:
*
* int32[0]: -108 // request id
- * int32[1]: 5 // messageType = SwitchUserMessageType::ANDROID_SWITCH
+ * int32[1]: 5 // messageType = SwitchUserMessageType::ANDROID_POST_SWITCH
* int32[2]: 11 // target user id
- * int32[3]: 11 // target user id flags (none)
+ * int32[3]: 0 // target user id flags (none)
* int32[4]: 11 // current user
* int32[5]: 0 // current user flags (none)
* int32[6]: 3 // number of users
@@ -2664,17 +2685,21 @@
*
* 5.ANDROID_POST_SWITCH
* ---------------------
- * Called by the Android System after a request to switch a user was made
+ * Called by the Android System after a request to switch a user was made.
*
* This property is called after switch requests of any type (i.e., LEGACY_ANDROID_SWITCH,
* ANDROID_SWITCH, or VEHICLE_REQUEST) and can be used to determine if the request succeeded or
* failed:
*
- * 1. When it succeeded, it's called when the Android user is in the boot locked state and the
- * value of the current and target users ids in the response are different. This would be
- * equivalent to receiving an Intent.ACTION_LOCKED_BOOT_COMPLETED in an Android app.
+ * 1. When it succeeded, it's called when the Android user is in the unlocked state and the
+ * value of the current and target users ids in the response are the same. This would be
+ * equivalent to receiving an Intent.ACTION_USER_UNLOCKED in an Android app.
* 2. When it failed it's called right away and the value of the current and target users ids
- * in the response are the same.
+ * in the response are different (as the current user didn't change to the target).
+ * 3. If a new switch request is made before the HAL responded to the previous one or before
+ * the user was unlocked, then the ANDROID_POST_SWITCH request is not made. For example,
+ * the driver could accidentally switch to the wrong user which has lock crentials, then
+ * switch to the right one before entering the credentials.
*
* The HAL can update its internal state once it receives this request, but it doesn't need to
* reply back to the Android System.
@@ -2824,7 +2849,7 @@
* int32[0]: 0 (Android user flags)
* int32[1]: 1 (number of associations being set)
* int32[2]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
- * int32[3]: 1 (1st value: UserIdentificationAssociationSETValue::ASSOCIATE_CURRENT_USER)
+ * int32[3]: 1 (1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER)
*
* If the request succeeded, the response would be simply:
*
diff --git a/biometrics/face/1.0/vts/functional/Android.bp b/biometrics/face/1.0/vts/functional/Android.bp
index f2598a7..ff4a6de 100644
--- a/biometrics/face/1.0/vts/functional/Android.bp
+++ b/biometrics/face/1.0/vts/functional/Android.bp
@@ -19,6 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalBiometricsFaceV1_0TargetTest.cpp"],
static_libs: ["android.hardware.biometrics.face@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/biometrics/fingerprint/2.1/default/Android.bp b/biometrics/fingerprint/2.1/default/Android.bp
index 497fa3f..ec4838b 100644
--- a/biometrics/fingerprint/2.1/default/Android.bp
+++ b/biometrics/fingerprint/2.1/default/Android.bp
@@ -2,6 +2,7 @@
name: "android.hardware.biometrics.fingerprint@2.1-service",
defaults: ["hidl_defaults"],
init_rc: ["android.hardware.biometrics.fingerprint@2.1-service.rc"],
+ vintf_fragments: ["android.hardware.biometrics.fingerprint@2.1-service.xml"],
vendor: true,
relative_install_path: "hw",
srcs: [
diff --git a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.xml b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.xml
new file mode 100644
index 0000000..115dd7b
--- /dev/null
+++ b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.biometrics.fingerprint</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <interface>
+ <name>IBiometricsFingerprint</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/biometrics/fingerprint/2.1/vts/functional/Android.bp b/biometrics/fingerprint/2.1/vts/functional/Android.bp
index c418032..7e3f340 100644
--- a/biometrics/fingerprint/2.1/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.1/vts/functional/Android.bp
@@ -19,6 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
static_libs: ["android.hardware.biometrics.fingerprint@2.1"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/biometrics/fingerprint/2.2/vts/functional/Android.bp b/biometrics/fingerprint/2.2/vts/functional/Android.bp
index 496570c..5e8e7c8 100644
--- a/biometrics/fingerprint/2.2/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.2/vts/functional/Android.bp
@@ -24,6 +24,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/bluetooth/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index cf25cc8..463ed84 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -24,6 +24,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/bluetooth/1.1/vts/functional/Android.bp b/bluetooth/1.1/vts/functional/Android.bp
index 8d6d749..eb4a720 100644
--- a/bluetooth/1.1/vts/functional/Android.bp
+++ b/bluetooth/1.1/vts/functional/Android.bp
@@ -23,5 +23,5 @@
"android.hardware.bluetooth@1.0",
"libbluetooth-types",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/bluetooth/a2dp/1.0/vts/functional/Android.bp b/bluetooth/a2dp/1.0/vts/functional/Android.bp
index e50e167..df18fcc 100644
--- a/bluetooth/a2dp/1.0/vts/functional/Android.bp
+++ b/bluetooth/a2dp/1.0/vts/functional/Android.bp
@@ -23,5 +23,5 @@
"android.hardware.bluetooth.a2dp@1.0",
"libbluetooth-types",
],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
index d8d0c29..44b138a 100644
--- a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
+++ b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
@@ -19,12 +19,14 @@
#include <android-base/logging.h>
#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioHost.h>
#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioOffload.h>
+#include <gtest/gtest.h>
#include <hardware/bluetooth.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/ServiceManagement.h>
#include <utils/Log.h>
#include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
using ::android::sp;
using ::android::hardware::Return;
@@ -38,34 +40,12 @@
using ::android::hardware::bluetooth::a2dp::V1_0::SampleRate;
using ::android::hardware::bluetooth::a2dp::V1_0::Status;
-// Test environment for Bluetooth HIDL A2DP HAL.
-class BluetoothA2dpHidlEnvironment
- : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static BluetoothA2dpHidlEnvironment* Instance() {
- static BluetoothA2dpHidlEnvironment* instance =
- new BluetoothA2dpHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override {
- registerTestService<IBluetoothAudioOffload>();
- }
-
- private:
- BluetoothA2dpHidlEnvironment() {}
-};
-
// The main test class for Bluetooth A2DP HIDL HAL.
-class BluetoothA2dpHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class BluetoothA2dpHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
// currently test passthrough mode only
- audio_offload =
- ::testing::VtsHalHidlTargetTestBase::getService<IBluetoothAudioOffload>(
- BluetoothA2dpHidlEnvironment::Instance()
- ->getServiceName<IBluetoothAudioOffload>());
+ audio_offload = IBluetoothAudioOffload::getService(GetParam());
ASSERT_NE(audio_offload, nullptr);
audio_host = new BluetoothAudioHost(*this);
@@ -115,19 +95,16 @@
};
// Empty test: Initialize()/Close() are called in SetUp()/TearDown().
-TEST_F(BluetoothA2dpHidlTest, InitializeAndClose) {}
+TEST_P(BluetoothA2dpHidlTest, InitializeAndClose) {}
// Test start and end session
-TEST_F(BluetoothA2dpHidlTest, StartAndEndSession) {
+TEST_P(BluetoothA2dpHidlTest, StartAndEndSession) {
EXPECT_EQ(Status::SUCCESS, audio_offload->startSession(audio_host, codec));
audio_offload->endSession();
}
-int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(BluetoothA2dpHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- BluetoothA2dpHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, BluetoothA2dpHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IBluetoothAudioOffload::descriptor)),
+ android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/bluetooth/audio/2.0/vts/functional/Android.bp b/bluetooth/audio/2.0/vts/functional/Android.bp
index b778b97..0ed5da4 100644
--- a/bluetooth/audio/2.0/vts/functional/Android.bp
+++ b/bluetooth/audio/2.0/vts/functional/Android.bp
@@ -9,5 +9,5 @@
shared_libs: [
"libfmq",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/boot/1.0/vts/functional/Android.bp b/boot/1.0/vts/functional/Android.bp
index 5244b95..92c818c 100644
--- a/boot/1.0/vts/functional/Android.bp
+++ b/boot/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalBootV1_0TargetTest.cpp"],
static_libs: ["android.hardware.boot@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/boot/1.1/vts/functional/Android.bp b/boot/1.1/vts/functional/Android.bp
index 49ea09a..9f0c74a 100644
--- a/boot/1.1/vts/functional/Android.bp
+++ b/boot/1.1/vts/functional/Android.bp
@@ -23,6 +23,8 @@
"android.hardware.boot@1.1",
"libgmock",
],
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "vts",
+ ],
}
-
diff --git a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
index 7c58ef3..30b965d 100644
--- a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
+++ b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
@@ -76,7 +76,11 @@
for (const auto value : ValidMergeStatusValues()) {
EXPECT_TRUE(boot->setSnapshotMergeStatus(value).withDefault(false));
auto status = boot->getSnapshotMergeStatus();
- EXPECT_EQ(status, value);
+ if (value == MergeStatus::SNAPSHOTTED) {
+ EXPECT_TRUE(status == MergeStatus::SNAPSHOTTED || status == MergeStatus::NONE);
+ } else {
+ EXPECT_EQ(status, value);
+ }
}
}
diff --git a/broadcastradio/1.0/vts/functional/Android.bp b/broadcastradio/1.0/vts/functional/Android.bp
index 9ba9fbe..2a4f942 100644
--- a/broadcastradio/1.0/vts/functional/Android.bp
+++ b/broadcastradio/1.0/vts/functional/Android.bp
@@ -22,5 +22,8 @@
"android.hardware.broadcastradio@1.0",
"android.hardware.broadcastradio@vts-utils-lib",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
diff --git a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
index 90c8463..9897ab7 100644
--- a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
+++ b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
@@ -15,11 +15,13 @@
*/
#define LOG_TAG "BroadcastRadioHidlHalTest"
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
#include <utils/threads.h>
#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
@@ -27,28 +29,28 @@
#include <android/hardware/broadcastradio/1.0/ITuner.h>
#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
#include <android/hardware/broadcastradio/1.0/types.h>
-#include <broadcastradio-vts-utils/environment-utils.h>
+#include <broadcastradio-vts-utils/hal-1.x-enum-utils.h>
-using ::android::sp;
-using ::android::Mutex;
using ::android::Condition;
+using ::android::Mutex;
+using ::android::sp;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
-using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
-using ::android::hardware::broadcastradio::V1_0::ITuner;
-using ::android::hardware::broadcastradio::V1_0::ITunerCallback;
-using ::android::hardware::broadcastradio::V1_0::Result;
-using ::android::hardware::broadcastradio::V1_0::Class;
-using ::android::hardware::broadcastradio::V1_0::Properties;
using ::android::hardware::broadcastradio::V1_0::Band;
using ::android::hardware::broadcastradio::V1_0::BandConfig;
+using ::android::hardware::broadcastradio::V1_0::Class;
using ::android::hardware::broadcastradio::V1_0::Direction;
-using ::android::hardware::broadcastradio::V1_0::ProgramInfo;
+using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
+using ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
+using ::android::hardware::broadcastradio::V1_0::ITuner;
+using ::android::hardware::broadcastradio::V1_0::ITunerCallback;
using ::android::hardware::broadcastradio::V1_0::MetaData;
using ::android::hardware::broadcastradio::V1_0::MetadataKey;
using ::android::hardware::broadcastradio::V1_0::MetadataType;
-using ::android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
+using ::android::hardware::broadcastradio::V1_0::ProgramInfo;
+using ::android::hardware::broadcastradio::V1_0::Properties;
+using ::android::hardware::broadcastradio::V1_0::Result;
+using ::android::hardware::broadcastradio::V1_0::vts::RadioClassFromString;
#define RETURN_IF_SKIPPED \
if (skipped) { \
@@ -56,19 +58,19 @@
return; \
}
-static BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>* gEnv = nullptr;
// The main test class for Broadcast Radio HIDL HAL.
-class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase,
- public ::testing::WithParamInterface<Class> {
- protected:
+class BroadcastRadioHidlTest
+ : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+ protected:
virtual void SetUp() override {
ASSERT_EQ(nullptr, mRadio.get());
- radioClass = GetParam();
+ radioClass = RadioClassFromString(std::get<1>(GetParam()));
+
skipped = false;
sp<IBroadcastRadioFactory> factory =
- getService<IBroadcastRadioFactory>(gEnv->getServiceName<IBroadcastRadioFactory>());
+ IBroadcastRadioFactory::getService(std::get<0>(GetParam()));
ASSERT_NE(nullptr, factory.get());
Result connectResult;
@@ -727,16 +729,8 @@
}
INSTANTIATE_TEST_CASE_P(
- BroadcastRadioHidlTestCases,
- BroadcastRadioHidlTest,
- ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
-
-int main(int argc, char** argv) {
- gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>;
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
-}
+ PerInstance, BroadcastRadioHidlTest,
+ testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IBroadcastRadioFactory::descriptor)),
+ ::testing::Values("AM_FM", "SAT", "DT")),
+ android::hardware::PrintInstanceTupleNameToString<>);
\ No newline at end of file
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index 0a02a69..661439a 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -25,5 +25,8 @@
"android.hardware.broadcastradio@vts-utils-lib",
"libgmock",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index 6687731..4833beb 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -16,7 +16,6 @@
#define LOG_TAG "broadcastradio.vts"
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
@@ -25,13 +24,16 @@
#include <android/hardware/broadcastradio/1.1/types.h>
#include <broadcastradio-utils-1x/Utils.h>
#include <broadcastradio-vts-utils/call-barrier.h>
-#include <broadcastradio-vts-utils/environment-utils.h>
+#include <broadcastradio-vts-utils/hal-1.x-enum-utils.h>
#include <broadcastradio-vts-utils/mock-timeout.h>
#include <broadcastradio-vts-utils/pointer-utils.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
#include <utils/threads.h>
#include <chrono>
@@ -51,6 +53,7 @@
using testing::Invoke;
using testing::SaveArg;
+using broadcastradio::V1_0::vts::RadioClassFromString;
using broadcastradio::vts::CallBarrier;
using V1_0::BandConfig;
using V1_0::Class;
@@ -59,7 +62,6 @@
using V1_0::MetadataType;
using broadcastradio::vts::clearAndWait;
-using broadcastradio::vts::BroadcastRadioHidlEnvironment;
static constexpr auto kConfigTimeout = 10s;
static constexpr auto kConnectModuleTimeout = 1s;
@@ -93,11 +95,9 @@
MOCK_TIMEOUT_METHOD1(currentProgramInfoChanged, Return<void>(const ProgramInfo&));
};
-static BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>* gEnv = nullptr;
-
-class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
- public ::testing::WithParamInterface<Class> {
- protected:
+class BroadcastRadioHalTest
+ : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+ protected:
virtual void SetUp() override;
virtual void TearDown() override;
@@ -120,11 +120,10 @@
};
void BroadcastRadioHalTest::SetUp() {
- radioClass = GetParam();
+ radioClass = RadioClassFromString(std::get<1>(GetParam()));
// lookup HIDL service
- auto factory =
- getService<IBroadcastRadioFactory>(gEnv->getServiceName<IBroadcastRadioFactory>());
+ auto factory = IBroadcastRadioFactory::getService(std::get<0>(GetParam()));
ASSERT_NE(nullptr, factory.get());
// connect radio module
@@ -601,24 +600,15 @@
} while (nextBand());
}
-INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
- ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
+INSTANTIATE_TEST_CASE_P(
+ PerInstance, BroadcastRadioHalTest,
+ testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+ IBroadcastRadioFactory::descriptor)),
+ ::testing::Values("AM_FM", "SAT", "DT")),
+ android::hardware::PrintInstanceTupleNameToString<>);
} // namespace vts
} // namespace V1_1
} // namespace broadcastradio
} // namespace hardware
} // namespace android
-
-int main(int argc, char** argv) {
- using android::hardware::broadcastradio::V1_1::vts::gEnv;
- using android::hardware::broadcastradio::V1_1::IBroadcastRadioFactory;
- using android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
- gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>;
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
-}
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index 49bb665..be17da3 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -27,6 +27,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/broadcastradio/common/vts/utils/Android.bp b/broadcastradio/common/vts/utils/Android.bp
index d3edc76..24fea0b 100644
--- a/broadcastradio/common/vts/utils/Android.bp
+++ b/broadcastradio/common/vts/utils/Android.bp
@@ -25,8 +25,5 @@
"-Wextra",
"-Werror",
],
- static_libs: [
- "VtsHalHidlTargetTestBase",
- ],
group_static_libs: true,
}
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/environment-utils.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/environment-utils.h
deleted file mode 100644
index 274e632..0000000
--- a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/environment-utils.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_VTS_ENVIRONMENT_UTILS
-#define ANDROID_HARDWARE_BROADCASTRADIO_VTS_ENVIRONMENT_UTILS
-
-#include <VtsHalHidlTargetTestEnvBase.h>
-
-namespace android {
-namespace hardware {
-namespace broadcastradio {
-namespace vts {
-
-// Test environment for BroadcastRadio HIDL HAL.
-template <typename... T>
-class BroadcastRadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- virtual void registerTestServices() override {
- using expander = int[];
- (void)expander{0, (registerTestService<T>(), 0)...};
- }
-};
-
-} // namespace vts
-} // namespace broadcastradio
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_BROADCASTRADIO_VTS_ENVIRONMENT_UTILS
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/hal-1.x-enum-utils.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/hal-1.x-enum-utils.h
new file mode 100644
index 0000000..6059ef8
--- /dev/null
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/hal-1.x-enum-utils.h
@@ -0,0 +1,38 @@
+/*
+ * 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
+
+namespace android::hardware::broadcastradio::V1_0::vts {
+
+using android::hardware::broadcastradio::V1_0::Class;
+
+/**
+ * Convert a string of Class name to its enum value. Fail the test if the enum
+ * value is not found.
+ *
+ * @param className string value of a Class enum.
+ * @return Class enum that matches the string value.
+ */
+Class RadioClassFromString(std::string className) {
+ if (className == "AM_FM") return Class::AM_FM;
+ if (className == "SAT") return Class::SAT;
+ if (className == "DT") return Class::DT;
+ // Fail the test run.
+ CHECK(false) << "Class name not found: " << className;
+ // Return some arbitrary enum.
+ return Class::AM_FM;
+}
+} // namespace android::hardware::broadcastradio::V1_0::vts
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 4b9d6f1..cd66f74 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -49,5 +49,5 @@
"libhidlmemory",
"libgralloctypes",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 05b8b47..bf5fbfe 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -18,12 +18,13 @@
#include <algorithm>
#include <chrono>
+#include <condition_variable>
+#include <list>
#include <mutex>
#include <regex>
#include <string>
#include <unordered_map>
#include <unordered_set>
-#include <condition_variable>
#include <inttypes.h>
@@ -165,6 +166,26 @@
YUV_REPROCESS,
};
+enum SystemCameraKind {
+ /**
+ * These camera devices are visible to all apps and system components alike
+ */
+ PUBLIC = 0,
+
+ /**
+ * These camera devices are visible only to processes having the
+ * android.permission.SYSTEM_CAMERA permission. They are not exposed to 3P
+ * apps.
+ */
+ SYSTEM_ONLY_CAMERA,
+
+ /**
+ * These camera devices are visible only to HAL clients (that try to connect
+ * on a hwbinder thread).
+ */
+ HIDDEN_SECURE_CAMERA
+};
+
namespace {
// "device@<version>/legacy/<id>"
const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)";
@@ -851,6 +872,8 @@
static Status isAutoFocusModeAvailable(
CameraParameters &cameraParams, const char *mode) ;
static Status isMonochromeCamera(const camera_metadata_t *staticMeta);
+ static Status getSystemCameraKind(const camera_metadata_t* staticMeta,
+ SystemCameraKind* systemCameraKind);
// Used by switchToOffline where a new result queue is created for offline reqs
void updateInflightResultQueue(std::shared_ptr<ResultMetadataQueue> resultQueue);
@@ -2555,6 +2578,90 @@
}
}
+TEST_P(CameraHidlTest, systemCameraTest) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ std::map<std::string, std::list<SystemCameraKind>> hiddenPhysicalIdToLogicalMap;
+ for (const auto& name : cameraDeviceNames) {
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ switch (deviceVersion) {
+ case CAMERA_DEVICE_API_VERSION_3_6:
+ case CAMERA_DEVICE_API_VERSION_3_5:
+ case CAMERA_DEVICE_API_VERSION_3_4:
+ case CAMERA_DEVICE_API_VERSION_3_3:
+ case CAMERA_DEVICE_API_VERSION_3_2: {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
+ ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+ Return<void> ret;
+ ret = mProvider->getCameraDeviceInterface_V3_x(
+ name, [&](auto status, const auto& device) {
+ ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(device, nullptr);
+ device3_x = device;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
+ ASSERT_EQ(status, Status::OK);
+ const camera_metadata_t* staticMeta =
+ reinterpret_cast<const camera_metadata_t*>(chars.data());
+ ASSERT_NE(staticMeta, nullptr);
+ Status rc = isLogicalMultiCamera(staticMeta);
+ ASSERT_TRUE(Status::OK == rc || Status::METHOD_NOT_SUPPORTED == rc);
+ if (Status::METHOD_NOT_SUPPORTED == rc) {
+ return;
+ }
+ std::unordered_set<std::string> physicalIds;
+ ASSERT_EQ(Status::OK, getPhysicalCameraIds(staticMeta, &physicalIds));
+ SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+ rc = getSystemCameraKind(staticMeta, &systemCameraKind);
+ ASSERT_EQ(rc, Status::OK);
+ for (auto physicalId : physicalIds) {
+ bool isPublicId = false;
+ for (auto& deviceName : cameraDeviceNames) {
+ std::string publicVersion, publicId;
+ ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, &publicVersion,
+ &publicId));
+ if (physicalId == publicId) {
+ isPublicId = true;
+ break;
+ }
+ }
+ // For hidden physical cameras, collect their associated logical cameras
+ // and store the system camera kind.
+ if (!isPublicId) {
+ auto it = hiddenPhysicalIdToLogicalMap.find(physicalId);
+ if (it == hiddenPhysicalIdToLogicalMap.end()) {
+ hiddenPhysicalIdToLogicalMap.insert(std::make_pair(
+ physicalId, std::list<SystemCameraKind>(systemCameraKind)));
+ } else {
+ it->second.push_back(systemCameraKind);
+ }
+ }
+ }
+ });
+ ASSERT_TRUE(ret.isOk());
+ } break;
+ case CAMERA_DEVICE_API_VERSION_1_0: {
+ // Not applicable
+ } break;
+ default: {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ } break;
+ }
+ }
+
+ // Check that the system camera kind of the logical cameras associated with
+ // each hidden physical camera is the same.
+ for (const auto& it : hiddenPhysicalIdToLogicalMap) {
+ SystemCameraKind neededSystemCameraKind = it.second.front();
+ for (auto foundSystemCamera : it.second) {
+ ASSERT_EQ(neededSystemCameraKind, foundSystemCamera);
+ }
+ }
+}
+
// Verify that the static camera characteristics can be retrieved
// successfully.
TEST_P(CameraHidlTest, getCameraCharacteristics) {
@@ -5671,6 +5778,39 @@
return ret;
}
+Status CameraHidlTest::getSystemCameraKind(const camera_metadata_t* staticMeta,
+ SystemCameraKind* systemCameraKind) {
+ Status ret = Status::OK;
+ if (nullptr == staticMeta || nullptr == systemCameraKind) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+ &entry);
+ if (0 != rc) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+
+ if (entry.count == 1 &&
+ entry.data.u8[0] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA) {
+ *systemCameraKind = SystemCameraKind::HIDDEN_SECURE_CAMERA;
+ return ret;
+ }
+
+ // Go through the capabilities and check if it has
+ // ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA
+ for (size_t i = 0; i < entry.count; ++i) {
+ uint8_t capability = entry.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA) {
+ *systemCameraKind = SystemCameraKind::SYSTEM_ONLY_CAMERA;
+ return ret;
+ }
+ }
+ *systemCameraKind = SystemCameraKind::PUBLIC;
+ return ret;
+}
+
// Check whether this is a monochrome camera using the static camera characteristics.
Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) {
Status ret = Status::METHOD_NOT_SUPPORTED;
@@ -6391,8 +6531,10 @@
const hidl_vec<hidl_string>& deviceNames) {
const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
ASSERT_NE(nullptr, metadata);
-
- Status rc = isLogicalMultiCamera(metadata);
+ SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+ Status rc = getSystemCameraKind(metadata, &systemCameraKind);
+ ASSERT_EQ(rc, Status::OK);
+ rc = isLogicalMultiCamera(metadata);
ASSERT_TRUE(Status::OK == rc || Status::METHOD_NOT_SUPPORTED == rc);
if (Status::METHOD_NOT_SUPPORTED == rc) {
return;
@@ -6411,6 +6553,7 @@
ASSERT_NE(physicalId, cameraId);
bool isPublicId = false;
std::string fullPublicId;
+ SystemCameraKind physSystemCameraKind = SystemCameraKind::PUBLIC;
for (auto& deviceName : deviceNames) {
std::string publicVersion, publicId;
ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId));
@@ -6434,9 +6577,16 @@
ret = subDevice->getCameraCharacteristics(
[&](auto status, const auto& chars) {
ASSERT_EQ(Status::OK, status);
- retcode = find_camera_metadata_ro_entry(
- (const camera_metadata_t *)chars.data(),
- ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+ const camera_metadata_t* staticMeta =
+ reinterpret_cast<const camera_metadata_t*>(chars.data());
+ rc = getSystemCameraKind(staticMeta, &physSystemCameraKind);
+ ASSERT_EQ(rc, Status::OK);
+ // Make sure that the system camera kind of a non-hidden
+ // physical cameras is the same as the logical camera associated
+ // with it.
+ ASSERT_EQ(physSystemCameraKind, systemCameraKind);
+ retcode = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2);
ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange);
});
@@ -6452,17 +6602,16 @@
ASSERT_NE(device3_5, nullptr);
// Check camera characteristics for hidden camera id
- Return<void> ret = device3_5->getPhysicalCameraCharacteristics(physicalId,
- [&](auto status, const auto& chars) {
- verifyCameraCharacteristics(status, chars);
- verifyMonochromeCharacteristics(chars, deviceVersion);
-
- retcode = find_camera_metadata_ro_entry(
- (const camera_metadata_t *)chars.data(),
- ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
- bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2);
- ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange);
- });
+ Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
+ physicalId, [&](auto status, const auto& chars) {
+ verifyCameraCharacteristics(status, chars);
+ verifyMonochromeCharacteristics(chars, deviceVersion);
+ retcode =
+ find_camera_metadata_ro_entry((const camera_metadata_t*)chars.data(),
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+ bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2);
+ ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange);
+ });
ASSERT_TRUE(ret.isOk());
// Check calling getCameraDeviceInterface_V3_x() on hidden camera id returns
diff --git a/cas/1.0/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp
index ab39c0e..82dc568 100644
--- a/cas/1.0/vts/functional/Android.bp
+++ b/cas/1.0/vts/functional/Android.bp
@@ -29,6 +29,6 @@
shared_libs: [
"libbinder",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/cas/1.1/vts/functional/Android.bp b/cas/1.1/vts/functional/Android.bp
index 9e8eb52..de223c8 100644
--- a/cas/1.1/vts/functional/Android.bp
+++ b/cas/1.1/vts/functional/Android.bp
@@ -30,6 +30,6 @@
shared_libs: [
"libbinder",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/cas/1.2/vts/functional/Android.bp b/cas/1.2/vts/functional/Android.bp
index 2d6517f..74ea85f 100644
--- a/cas/1.2/vts/functional/Android.bp
+++ b/cas/1.2/vts/functional/Android.bp
@@ -33,6 +33,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index f55e799..0731230 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -18,4 +18,5 @@
enabled: false,
},
},
+ versions: ["1"],
}
diff --git a/common/aidl/aidl_api/android.hardware.common/1/.hash b/common/aidl/aidl_api/android.hardware.common/1/.hash
new file mode 100644
index 0000000..ad5102a
--- /dev/null
+++ b/common/aidl/aidl_api/android.hardware.common/1/.hash
@@ -0,0 +1 @@
+59e782d6ed4c2aed3744d37fb751ee23797835dd
diff --git a/common/aidl/aidl_api/android.hardware.common/1/android/hardware/common/NativeHandle.aidl b/common/aidl/aidl_api/android.hardware.common/1/android/hardware/common/NativeHandle.aidl
new file mode 100644
index 0000000..f37b7d5
--- /dev/null
+++ b/common/aidl/aidl_api/android.hardware.common/1/android/hardware/common/NativeHandle.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.common;
+@VintfStability
+parcelable NativeHandle {
+ ParcelFileDescriptor[] fds;
+ int[] ints;
+}
diff --git a/compatibility_matrices/build/vintf_compatibility_matrix.go b/compatibility_matrices/build/vintf_compatibility_matrix.go
index e48f993..2772ba3 100644
--- a/compatibility_matrices/build/vintf_compatibility_matrix.go
+++ b/compatibility_matrices/build/vintf_compatibility_matrix.go
@@ -40,7 +40,15 @@
Description: "assemble_vintf -i ${inputs}",
}, "inputs")
- kernelConfigTag = dependencyTag{name: "kernel-config"}
+ xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", blueprint.RuleParams{
+ Command: `$XmlLintCmd --schema $xsd $in > /dev/null && touch -a $out`,
+ CommandDeps: []string{"$XmlLintCmd"},
+ Restat: true,
+ }, "xsd")
+
+ kernelConfigTag = dependencyTag{name: "kernel-config"}
+ schemaTag = dependencyTag{name: "matrix-schema"}
+ schemaModuleName = "compatibility_matrix_schema"
)
const (
@@ -62,11 +70,13 @@
android.ModuleBase
properties vintfCompatibilityMatrixProperties
- genFile android.WritablePath
+ genFile android.WritablePath
+ additionalDependencies android.WritablePaths
}
func init() {
pctx.HostBinToolVariable("assembleVintfCmd", "assemble_vintf")
+ pctx.HostBinToolVariable("XmlLintCmd", "xmllint")
android.RegisterModuleType("vintf_compatibility_matrix", vintfCompatibilityMatrixFactory)
}
@@ -82,6 +92,42 @@
func (g *vintfCompatibilityMatrixRule) DepsMutator(ctx android.BottomUpMutatorContext) {
android.ExtractSourcesDeps(ctx, g.properties.Srcs)
ctx.AddDependency(ctx.Module(), kernelConfigTag, g.properties.Kernel_configs...)
+ ctx.AddDependency(ctx.Module(), schemaTag, schemaModuleName)
+}
+
+func (g *vintfCompatibilityMatrixRule) timestampFilePath(ctx android.ModuleContext, path android.Path) android.WritablePath {
+ return android.GenPathWithExt(ctx, "vintf-xmllint", path, "ts")
+}
+
+func (g *vintfCompatibilityMatrixRule) generateValidateBuildAction(ctx android.ModuleContext, path android.Path, schema android.Path) {
+ timestamp := g.timestampFilePath(ctx, path)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: xmllintXsd,
+ Description: "xmllint-xsd",
+ Input: path,
+ Output: timestamp,
+ Implicit: schema,
+ Args: map[string]string{
+ "xsd": schema.String(),
+ },
+ })
+ g.additionalDependencies = append(g.additionalDependencies, timestamp)
+}
+
+func (g *vintfCompatibilityMatrixRule) getSchema(ctx android.ModuleContext) android.OptionalPath {
+ schemaModule := ctx.GetDirectDepWithTag(schemaModuleName, schemaTag)
+ sfp, ok := schemaModule.(android.SourceFileProducer)
+ if !ok {
+ ctx.ModuleErrorf("Implicit dependency %q has no srcs", ctx.OtherModuleName(schemaModule))
+ return android.OptionalPath{}
+ }
+
+ schemaSrcs := sfp.Srcs()
+ if len(schemaSrcs) != 1 {
+ ctx.PropertyErrorf(`srcs of implicit dependency %q has length %d != 1`, ctx.OtherModuleName(schemaModule), len(schemaSrcs))
+ return android.OptionalPath{}
+ }
+ return android.OptionalPathForPath(schemaSrcs[0])
}
func (g *vintfCompatibilityMatrixRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -91,7 +137,18 @@
outputFilename = g.Name()
}
+ schema := g.getSchema(ctx)
+ if !schema.Valid() {
+ return
+ }
+
inputPaths := android.PathsForModuleSrc(ctx, g.properties.Srcs)
+ for _, srcPath := range inputPaths {
+ g.generateValidateBuildAction(ctx, srcPath, schema.Path())
+ }
+
+ // No need to validate matrices from kernel configs because they are generated by
+ // assemble_vintf.
ctx.VisitDirectDepsWithTag(kernelConfigTag, func(m android.Module) {
if k, ok := m.(*configs.KernelConfigRule); ok {
inputPaths = append(inputPaths, k.OutputPath())
@@ -112,6 +169,7 @@
"inputs": strings.Join(inputPaths.Strings(), ":"),
},
})
+ g.generateValidateBuildAction(ctx, g.genFile, schema.Path())
ctx.InstallFile(android.PathForModuleInstall(ctx, "etc", relpath), outputFilename, g.genFile)
}
@@ -126,6 +184,9 @@
if proptools.String(g.properties.Stem) != "" {
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", proptools.String(g.properties.Stem))
}
+ for _, path := range g.additionalDependencies {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", path.String())
+ }
},
},
}
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index 38f589d..e772b6f 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -72,7 +72,7 @@
<name>android.hardware.automotive.sv</name>
<version>1.0</version>
<interface>
- <name>ISurroundView</name>
+ <name>ISurroundViewService</name>
<instance>default</instance>
</interface>
</hal>
@@ -94,7 +94,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.biometrics.fingerprint</name>
- <version>2.1</version>
+ <version>2.1-2</version>
<interface>
<name>IBiometricsFingerprint</name>
<instance>default</instance>
@@ -157,14 +157,6 @@
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.configstore</name>
- <version>1.1</version>
- <interface>
- <name>ISurfaceFlingerConfigs</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl" optional="true">
<name>android.hardware.confirmationui</name>
<version>1.0</version>
<interface>
@@ -379,6 +371,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.radio</name>
+ <version>1.4</version>
<version>1.5</version>
<interface>
<name>IRadio</name>
diff --git a/configstore/1.0/vts/functional/Android.bp b/configstore/1.0/vts/functional/Android.bp
index 31d4b1c..4e1e045 100644
--- a/configstore/1.0/vts/functional/Android.bp
+++ b/configstore/1.0/vts/functional/Android.bp
@@ -19,6 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalConfigstoreV1_0TargetTest.cpp"],
static_libs: ["android.hardware.configstore@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/confirmationui/1.0/default/Android.bp b/confirmationui/1.0/default/Android.bp
index ecba064..33a1e07 100644
--- a/confirmationui/1.0/default/Android.bp
+++ b/confirmationui/1.0/default/Android.bp
@@ -17,6 +17,7 @@
cc_binary {
name: "android.hardware.confirmationui@1.0-service",
init_rc: ["android.hardware.confirmationui@1.0-service.rc"],
+ vintf_fragments: ["android.hardware.confirmationui@1.0-service.xml"],
vendor: true,
relative_install_path: "hw",
cflags: [
@@ -39,4 +40,4 @@
"liblog",
"libutils",
],
-}
\ No newline at end of file
+}
diff --git a/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.xml b/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.xml
new file mode 100644
index 0000000..9008b87
--- /dev/null
+++ b/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.confirmationui</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IConfirmationUI</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index c8b522c..c73ee28 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", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/contexthub/1.0/vts/functional/Android.bp b/contexthub/1.0/vts/functional/Android.bp
index d51c966..091f2dc 100644
--- a/contexthub/1.0/vts/functional/Android.bp
+++ b/contexthub/1.0/vts/functional/Android.bp
@@ -24,6 +24,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/contexthub/1.1/vts/functional/Android.bp b/contexthub/1.1/vts/functional/Android.bp
index f1625a6..034c11f 100644
--- a/contexthub/1.1/vts/functional/Android.bp
+++ b/contexthub/1.1/vts/functional/Android.bp
@@ -25,6 +25,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/current.txt b/current.txt
index 183d006..d2b7206 100644
--- a/current.txt
+++ b/current.txt
@@ -1,6 +1,10 @@
# Do not change this file except to add new interfaces. Changing
# pre-existing interfaces will fail VTS and break framework-only OTAs
+# Test HALs
+
+717c17cd380bb48710dff601d1a03351d4ebc28028353d5d60489248f506523c android.hardware.tests.lazy@1.0::ILazy
+
# HALs released in Android O
f219c3b5b8c6cb1d659d4c7328f67246abfe1a8613f469826fd3b9ad090417a2 android.hardware.audio@2.0::IDevice
@@ -588,6 +592,7 @@
cd06a7911b9acd4a653bbf7133888878fbcb3f84be177c7a3f1becaae3d8618f android.hardware.camera.metadata@3.2::types
a05277065c28ebecd58118bd240fb8c55757361e8648c01f7c4dacdb7f2a95dc android.hardware.camera.metadata@3.3::types
9cb3df2bde2c6cd5fd96b7c41555420cacd7e276a556c684af91b7461c86460f android.hardware.gnss@1.0::IGnssCallback
+dd6cd9dba4fde99a1bc3cb1728d82309f509a6e6e1993e5042dfa5ffe4af5442 android.hardware.gnss@2.0::IGnssMeasurementCallback
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
@@ -635,29 +640,26 @@
4bc4e8087f5c389f013370ed68bc8a1a29cb2f203237937697f35e005a5ad0b4 android.hardware.automotive.audiocontrol@2.0::IAudioControl
37ef585d6687cb31e35c67ab456140d70edba9c4333ce5a6ddd70e636e985773 android.hardware.automotive.audiocontrol@2.0::ICloseHandle
3cf3e5e48ba2642052bbccc1aa4e8bb142933ac960ff40eeedd16e4fe452e7a5 android.hardware.automotive.audiocontrol@2.0::IFocusListener
-d06fc14b325beeef06bd39de8f178f490d9e9095255626866071aab42be1fc40 android.hardware.automotive.audiocontrol@2.0::types
+44c03f3341939524b5f5acb6680f8a91924d02e335a32840d56597616db7f1ea android.hardware.automotive.audiocontrol@2.0::types
949a2582c9efa3f6f631f56120eae3f02313f251dbf9246c327e419cdf0652a2 android.hardware.automotive.can@1.0::ICanBus
43cddb1907a30343bced68946884416ea25ab14ae2df4709357528b2bedba84c android.hardware.automotive.can@1.0::ICanController
272e826492b27b0dbdeda408e84a41ae43e98f29e57995b6452ded270aae4eee android.hardware.automotive.can@1.0::ICanErrorListener
07e387bd8bc0e4df5f372515ed960a0b1ae74ea7231d4490a0bb09b07046e4f1 android.hardware.automotive.can@1.0::ICanMessageListener
2166132d6c247630a193217b4338074f634d6691b1ed6796cb26b3812e90b46e android.hardware.automotive.can@1.0::ICloseHandle
83355471a3b6d7f777d3f129714585ffb77d9b6f8a3d0365741969631efb81b2 android.hardware.automotive.can@1.0::types
-8afd93d525cf17818e3d46e72f30debeaacc6fb166a59a8e25272f2baeb0ef7a android.hardware.automotive.evs@1.1::IEvsCamera
+50bfbeef15d7451bd07e4ad460fbcb7ff80521b89bb8049035c0d458b4125ae4 android.hardware.automotive.evs@1.1::IEvsCamera
89ff5ab18b3069f21a57f559b290caa50670f0ae1b74178f630183aef39b496b android.hardware.automotive.evs@1.1::IEvsCameraStream
4c67f768067a0aceac74381f6f62e778ab3b6a18f47db3c9b98c58190ef5619d android.hardware.automotive.evs@1.1::IEvsDisplay
87958d728d7c0ee9b9391ab4a072b097914921a7b38f7dc3df427f933a5b528e android.hardware.automotive.evs@1.1::IEvsEnumerator
f53b4e8de6209c6d0fa9036005671b34a2f98328b51423d3a5137a43bf42c84d android.hardware.automotive.evs@1.1::IEvsUltrasonicsArray
0460bacbde906a846a3d71b2b7b33d6927cac3ff072e523ffac7853577464406 android.hardware.automotive.evs@1.1::IEvsUltrasonicsArrayStream
-8a156203892de3cfa47baaccabef3c45b3315cae93b332357598d60896b1ac7f android.hardware.automotive.evs@1.1::types
+3e374b5c4777f959f62a320abb3b9edca8874e24e383dbb19c66d224f151b363 android.hardware.automotive.evs@1.1::types
4e4904c4067dadae974ddf90351f362331dcd04bba1d890d313cc8ba91f68c15 android.hardware.automotive.sv@1.0::ISurroundView2dSession
63336e9d03f545020ff2982ff76d9d8c44fa76ad476293b5ef6732cbbd71e61b android.hardware.automotive.sv@1.0::ISurroundView3dSession
b7015428cd52ce8192d13bfcbf2c4455cda3727d57f2aac80d65a1747104f5ac android.hardware.automotive.sv@1.0::ISurroundViewService
7d2e77ad86766bbc213fa7377eab739f44cc0866e567e6d33c0e27e7f99e27a8 android.hardware.automotive.sv@1.0::ISurroundViewSession
d34769e55df919739bb46f25ae2e125e9c807733afa94daeca20feadd74de79c android.hardware.automotive.sv@1.0::ISurroundViewStream
affd9c591f48a69773fcf43dc4a716d292cd4bc5ba2be8649276af0aedea435d android.hardware.automotive.sv@1.0::types
-b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
-7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
-6b2564fce1d364baf9ba15a5cb00a8f08f86a5be5387c0ede795328ca536a2c7 android.hardware.automotive.vehicle@2.0::types
140f8f62100ccf9cd282ae3685a0f4ef0a9f971d77dfbc7350ccb4e04cf295ec android.hardware.biometrics.fingerprint@2.2::IBiometricsFingerprint
82cad99f5feb2ea9bcd4579055edf4af8feb9fc602a6e4827ddd727d254d4991 android.hardware.biometrics.fingerprint@2.2::IBiometricsFingerprintClientCallback
ae6315fd42196478ac08441cb489d854118001bca5b9b9fd58af5110952be30e android.hardware.biometrics.fingerprint@2.2::types
@@ -711,7 +713,7 @@
278817920bfd5292a7713f97f1832cca53de3de640f7670e413d97c6e7fd581c android.hardware.neuralnetworks@1.3::IDevice
127ba11efb8220dc3aec9a8f441b59eaf1c68d7f03f577833e1824de75a36b17 android.hardware.neuralnetworks@1.3::IExecutionCallback
6e904be0ddca5ae1de8eba020e6c38ed935ea7d80cd08f47787f137a0ca58555 android.hardware.neuralnetworks@1.3::IFencedExecutionCallback
-2b0b10d2ea7a18a4048cd0eb83d35c19a817aeee95f65807fc31f4ef21381397 android.hardware.neuralnetworks@1.3::IPreparedModel
+ee9dc34b9925b8367b1111c72bd6d9d375432735e451572ca5a665d8516a7744 android.hardware.neuralnetworks@1.3::IPreparedModel
eee3430cc86c97c7b407495863d8fb61da6f1a64b7721e77b9b4909b11b174e9 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
acf84925f8ee0a651f2ec547ac334034de266479b93af5434f6c1f25e66aba96 android.hardware.neuralnetworks@1.3::types
b454df853441c12f6e425e8a60dd29fda20f5e6e39b93d1103e4b37495db38aa android.hardware.radio@1.5::IRadio
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 235bfb4..8fd258a 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -24,7 +24,7 @@
"vendor_modules.cpp",
],
static_libs: [
- "android.hardware.drm@1.0-helper",
+ "android.hardware.drm@1.0-helper",
],
export_include_dirs: ["include"],
}
@@ -84,8 +84,22 @@
"libcrypto_static",
"libdrmvtshelper",
],
+ arch: {
+ arm: {
+ data: [":libvtswidevine-arm-prebuilts"],
+ },
+ arm64: {
+ data: [":libvtswidevine-arm64-prebuilts"],
+ },
+ x86: {
+ data: [":libvtswidevine-x86-prebuilts"],
+ },
+ x86_64: {
+ data: [":libvtswidevine-x86_64-prebuilts"],
+ },
+ },
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/drm/1.0/vts/functional/AndroidTest.xml b/drm/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..92ea7e4
--- /dev/null
+++ b/drm/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalDrmV1_0TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="VtsHalDrmV1_0TargetTest" value="/data/local/tmp/VtsHalDrmV1_0TargetTest" />
+ <option name="push-file" key="libvtswidevine64.so" value="/data/local/tmp/64/lib/libvtswidevine.so" />
+ <option name="push-file" key="libvtswidevine32.so" value="/data/local/tmp/32/lib/libvtswidevine.so" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalDrmV1_0TargetTest" />
+ </test>
+</configuration>
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index e08d760..053a564 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -60,13 +60,27 @@
"drm_hal_test_main.cpp",
],
whole_static_libs: [
- "android.hardware.drm@1.1-vts"
+ "android.hardware.drm@1.1-vts",
],
shared_libs: [
"android.hardware.drm@1.1",
],
+ arch: {
+ arm: {
+ data: [":libvtswidevine-arm-prebuilts"],
+ },
+ arm64: {
+ data: [":libvtswidevine-arm64-prebuilts"],
+ },
+ x86: {
+ data: [":libvtswidevine-x86-prebuilts"],
+ },
+ x86_64: {
+ data: [":libvtswidevine-x86_64-prebuilts"],
+ },
+ },
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/drm/1.1/vts/functional/AndroidTest.xml b/drm/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..65c45ac
--- /dev/null
+++ b/drm/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalDrmV1_1TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="VtsHalDrmV1_1TargetTest" value="/data/local/tmp/VtsHalDrmV1_1TargetTest" />
+ <option name="push-file" key="libvtswidevine64.so" value="/data/local/tmp/64/lib/libvtswidevine.so" />
+ <option name="push-file" key="libvtswidevine32.so" value="/data/local/tmp/32/lib/libvtswidevine.so" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalDrmV1_1TargetTest" />
+ </test>
+</configuration>
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index ecc7d6c..9aed4ee 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -70,8 +70,22 @@
"libcrypto_static",
"libdrmvtshelper",
],
+ arch: {
+ arm: {
+ data: [":libvtswidevine-arm-prebuilts"],
+ },
+ arm64: {
+ data: [":libvtswidevine-arm64-prebuilts"],
+ },
+ x86: {
+ data: [":libvtswidevine-x86-prebuilts"],
+ },
+ x86_64: {
+ data: [":libvtswidevine-x86_64-prebuilts"],
+ },
+ },
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/drm/1.2/vts/functional/AndroidTest.xml b/drm/1.2/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..5da38ae
--- /dev/null
+++ b/drm/1.2/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalDrmV1_2TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="VtsHalDrmV1_2TargetTest" value="/data/local/tmp/VtsHalDrmV1_2TargetTest" />
+ <option name="push-file" key="libvtswidevine64.so" value="/data/local/tmp/64/lib/libvtswidevine.so" />
+ <option name="push-file" key="libvtswidevine32.so" value="/data/local/tmp/32/lib/libvtswidevine.so" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalDrmV1_2TargetTest" />
+ </test>
+</configuration>
diff --git a/drm/1.3/vts/functional/Android.bp b/drm/1.3/vts/functional/Android.bp
index ac1f912..3e40adf 100644
--- a/drm/1.3/vts/functional/Android.bp
+++ b/drm/1.3/vts/functional/Android.bp
@@ -71,8 +71,22 @@
"android.hardware.drm@1.0-helper",
"libdrmvtshelper",
],
+ arch: {
+ arm: {
+ data: [":libvtswidevine-arm-prebuilts"],
+ },
+ arm64: {
+ data: [":libvtswidevine-arm64-prebuilts"],
+ },
+ x86: {
+ data: [":libvtswidevine-x86-prebuilts"],
+ },
+ x86_64: {
+ data: [":libvtswidevine-x86_64-prebuilts"],
+ },
+ },
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/drm/1.3/vts/functional/AndroidTest.xml b/drm/1.3/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..338430f
--- /dev/null
+++ b/drm/1.3/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalDrmV1_3TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="VtsHalDrmV1_3TargetTest" value="/data/local/tmp/VtsHalDrmV1_3TargetTest" />
+ <option name="push-file" key="libvtswidevine64.so" value="/data/local/tmp/64/lib/libvtswidevine.so" />
+ <option name="push-file" key="libvtswidevine32.so" value="/data/local/tmp/32/lib/libvtswidevine.so" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalDrmV1_3TargetTest" />
+ </test>
+</configuration>
diff --git a/drm/1.3/vts/functional/drm_hal_test.cpp b/drm/1.3/vts/functional/drm_hal_test.cpp
index 738f5b2..0958c35 100644
--- a/drm/1.3/vts/functional/drm_hal_test.cpp
+++ b/drm/1.3/vts/functional/drm_hal_test.cpp
@@ -39,10 +39,10 @@
}
// signRSA
- const hidl_vec<uint8_t>& sessionId{};
- const hidl_string& algorithm{};
- const hidl_vec<uint8_t>& message{};
- const hidl_vec<uint8_t>& wrappedKey{};
+ const hidl_vec<uint8_t>& sessionId{0};
+ const hidl_string& algorithm{"RSASSA-PSS-SHA1"};
+ const hidl_vec<uint8_t>& message{0};
+ const hidl_vec<uint8_t>& wrappedKey{0};
auto res = drmPlugin_->signRSA(
sessionId, algorithm, message, wrappedKey,
[&](StatusV1_0 status, const hidl_vec<uint8_t>& signature) {
diff --git a/dumpstate/1.0/vts/functional/Android.bp b/dumpstate/1.0/vts/functional/Android.bp
index 3bac281..451b053 100644
--- a/dumpstate/1.0/vts/functional/Android.bp
+++ b/dumpstate/1.0/vts/functional/Android.bp
@@ -18,5 +18,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalDumpstateV1_0TargetTest.cpp"],
static_libs: ["android.hardware.dumpstate@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/dumpstate/1.1/vts/functional/Android.bp b/dumpstate/1.1/vts/functional/Android.bp
index 5267706..43a3c21 100644
--- a/dumpstate/1.1/vts/functional/Android.bp
+++ b/dumpstate/1.1/vts/functional/Android.bp
@@ -24,6 +24,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/gatekeeper/1.0/vts/functional/Android.bp b/gatekeeper/1.0/vts/functional/Android.bp
index a115285..1ca966d 100644
--- a/gatekeeper/1.0/vts/functional/Android.bp
+++ b/gatekeeper/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalGatekeeperV1_0TargetTest.cpp"],
static_libs: ["android.hardware.gatekeeper@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/gnss/1.0/vts/functional/Android.bp b/gnss/1.0/vts/functional/Android.bp
index d73b32e..45755e6 100644
--- a/gnss/1.0/vts/functional/Android.bp
+++ b/gnss/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalGnssV1_0TargetTest.cpp"],
static_libs: ["android.hardware.gnss@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index 369a89d..0d540b7 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -33,6 +33,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/gnss/2.0/IGnssMeasurementCallback.hal b/gnss/2.0/IGnssMeasurementCallback.hal
index e055f7a..76c7943 100644
--- a/gnss/2.0/IGnssMeasurementCallback.hal
+++ b/gnss/2.0/IGnssMeasurementCallback.hal
@@ -402,6 +402,8 @@
* Value "C" represents GPS L1 C/A, GPS L2 C/A, GLONASS G1 C/A, GLONASS G2 C/A, GALILEO E1C,
* GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C.
*
+ * value "D" represents BDS B1C D.
+ *
* Value "I" represents GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I, GALILEO E5a+b I,
* SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I.
*
@@ -411,7 +413,7 @@
*
* Value "N" represents GPS L1 codeless, GPS L2 codeless.
*
- * Value "P" represents GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P.
+ * Value "P" represents GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P, BDS B1C P.
*
* Value "Q" represents GPS L5 Q, GLONASS G3 Q, GALILEO E5a Q, GALILEO E5b Q, GALILEO E5a+b Q,
* SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q.
@@ -423,7 +425,7 @@
* Value "X" represents GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q), GLONASS G3 (I+Q),
* GALILEO E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q),
* GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q),
- * LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
+ * LEX(6) (S+L), BDS B1 (I+Q), BDS B1C (D+P), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
*
* Value "Y" represents GPS L1Y, GPS L2Y.
*
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index da5289d..d67677a 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -31,5 +31,5 @@
"android.hardware.gnss@2.1",
"android.hardware.gnss@common-vts-lib",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
index f008a26..b3051d4 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -34,6 +34,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 601cabc..c089a76 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -21,4 +21,5 @@
enabled: false,
},
},
+ versions: ["1"],
}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/.hash b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/.hash
new file mode 100644
index 0000000..66b5d13
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/.hash
@@ -0,0 +1 @@
+f5bdf5724a941dc7e5e7d0ebe9dfe028f7bcc25f
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/BlendMode.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/BlendMode.aidl
new file mode 100644
index 0000000..deafdfa
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/BlendMode.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum BlendMode {
+ INVALID = 0,
+ NONE = 1,
+ PREMULTIPLIED = 2,
+ COVERAGE = 3,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/BufferUsage.aidl
new file mode 100644
index 0000000..58eefc4
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/BufferUsage.aidl
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum BufferUsage {
+ CPU_READ_MASK = 15,
+ CPU_READ_NEVER = 0,
+ CPU_READ_RARELY = 2,
+ CPU_READ_OFTEN = 3,
+ CPU_WRITE_MASK = 240,
+ CPU_WRITE_NEVER = 0,
+ CPU_WRITE_RARELY = 32,
+ CPU_WRITE_OFTEN = 48,
+ GPU_TEXTURE = 256,
+ GPU_RENDER_TARGET = 512,
+ COMPOSER_OVERLAY = 2048,
+ COMPOSER_CLIENT_TARGET = 4096,
+ PROTECTED = 16384,
+ COMPOSER_CURSOR = 32768,
+ VIDEO_ENCODER = 65536,
+ CAMERA_OUTPUT = 131072,
+ CAMERA_INPUT = 262144,
+ RENDERSCRIPT = 1048576,
+ VIDEO_DECODER = 4194304,
+ SENSOR_DIRECT_DATA = 8388608,
+ GPU_CUBE_MAP = 33554432,
+ GPU_MIPMAP_COMPLETE = 67108864,
+ HW_IMAGE_ENCODER = 134217728,
+ GPU_DATA_BUFFER = 16777216,
+ VENDOR_MASK = -268435456,
+ VENDOR_MASK_HI = -281474976710656,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/ChromaSiting.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/ChromaSiting.aidl
new file mode 100644
index 0000000..7ca4dfa
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/ChromaSiting.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum ChromaSiting {
+ NONE = 0,
+ UNKNOWN = 1,
+ SITED_INTERSTITIAL = 2,
+ COSITED_HORIZONTAL = 3,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Compression.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Compression.aidl
new file mode 100644
index 0000000..06e40a0
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Compression.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum Compression {
+ NONE = 0,
+ DISPLAY_STREAM_COMPRESSION = 1,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Cta861_3.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Cta861_3.aidl
new file mode 100644
index 0000000..d4af501
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Cta861_3.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable Cta861_3 {
+ float maxContentLightLevel;
+ float maxFrameAverageLightLevel;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Dataspace.aidl
new file mode 100644
index 0000000..43d7f84
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Dataspace.aidl
@@ -0,0 +1,81 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum Dataspace {
+ UNKNOWN = 0,
+ ARBITRARY = 1,
+ STANDARD_SHIFT = 16,
+ STANDARD_MASK = 4128768,
+ STANDARD_UNSPECIFIED = 0,
+ STANDARD_BT709 = 65536,
+ STANDARD_BT601_625 = 131072,
+ STANDARD_BT601_625_UNADJUSTED = 196608,
+ STANDARD_BT601_525 = 262144,
+ STANDARD_BT601_525_UNADJUSTED = 327680,
+ STANDARD_BT2020 = 393216,
+ STANDARD_BT2020_CONSTANT_LUMINANCE = 458752,
+ STANDARD_BT470M = 524288,
+ STANDARD_FILM = 589824,
+ STANDARD_DCI_P3 = 655360,
+ STANDARD_ADOBE_RGB = 720896,
+ TRANSFER_SHIFT = 22,
+ TRANSFER_MASK = 130023424,
+ TRANSFER_UNSPECIFIED = 0,
+ TRANSFER_LINEAR = 4194304,
+ TRANSFER_SRGB = 8388608,
+ TRANSFER_SMPTE_170M = 12582912,
+ TRANSFER_GAMMA2_2 = 16777216,
+ TRANSFER_GAMMA2_6 = 20971520,
+ TRANSFER_GAMMA2_8 = 25165824,
+ TRANSFER_ST2084 = 29360128,
+ TRANSFER_HLG = 33554432,
+ RANGE_SHIFT = 27,
+ RANGE_MASK = 939524096,
+ RANGE_UNSPECIFIED = 0,
+ RANGE_FULL = 134217728,
+ RANGE_LIMITED = 268435456,
+ RANGE_EXTENDED = 402653184,
+ SRGB_LINEAR = 138477568,
+ SCRGB_LINEAR = 406913024,
+ SRGB = 142671872,
+ SCRGB = 411107328,
+ JFIF = 146931712,
+ BT601_625 = 281149440,
+ BT601_525 = 281280512,
+ BT709 = 281083904,
+ DCI_P3_LINEAR = 139067392,
+ DCI_P3 = 155844608,
+ DISPLAY_P3_LINEAR = 139067392,
+ DISPLAY_P3 = 143261696,
+ ADOBE_RGB = 151715840,
+ BT2020_LINEAR = 138805248,
+ BT2020 = 147193856,
+ BT2020_PQ = 163971072,
+ DEPTH = 4096,
+ SENSOR = 4097,
+ BT2020_ITU = 281411584,
+ BT2020_ITU_PQ = 298188800,
+ BT2020_ITU_HLG = 302383104,
+ BT2020_HLG = 168165376,
+ DISPLAY_BT2020 = 142999552,
+ DYNAMIC_DEPTH = 4098,
+ JPEG_APP_SEGMENTS = 4099,
+ HEIF = 4100,
+ BT709_FULL_RANGE = 146866176,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/ExtendableType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/ExtendableType.aidl
new file mode 100644
index 0000000..6fcb794
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/ExtendableType.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable ExtendableType {
+ @utf8InCpp String name;
+ long value = 0;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/HardwareBuffer.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/HardwareBuffer.aidl
new file mode 100644
index 0000000..72222e1
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/HardwareBuffer.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable HardwareBuffer {
+ android.hardware.graphics.common.HardwareBufferDescription description;
+ android.hardware.common.NativeHandle handle;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/HardwareBufferDescription.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/HardwareBufferDescription.aidl
new file mode 100644
index 0000000..8b12169
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/HardwareBufferDescription.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable HardwareBufferDescription {
+ int width;
+ int height;
+ int layers;
+ android.hardware.graphics.common.PixelFormat format;
+ android.hardware.graphics.common.BufferUsage usage;
+ int stride;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Interlaced.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Interlaced.aidl
new file mode 100644
index 0000000..26674c9
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Interlaced.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum Interlaced {
+ NONE = 0,
+ TOP_BOTTOM = 1,
+ RIGHT_LEFT = 2,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PixelFormat.aidl
new file mode 100644
index 0000000..e5f0470
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PixelFormat.aidl
@@ -0,0 +1,50 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum PixelFormat {
+ UNSPECIFIED = 0,
+ RGBA_8888 = 1,
+ RGBX_8888 = 2,
+ RGB_888 = 3,
+ RGB_565 = 4,
+ BGRA_8888 = 5,
+ YCBCR_422_SP = 16,
+ YCRCB_420_SP = 17,
+ YCBCR_422_I = 20,
+ RGBA_FP16 = 22,
+ RAW16 = 32,
+ BLOB = 33,
+ IMPLEMENTATION_DEFINED = 34,
+ YCBCR_420_888 = 35,
+ RAW_OPAQUE = 36,
+ RAW10 = 37,
+ RAW12 = 38,
+ RGBA_1010102 = 43,
+ Y8 = 538982489,
+ Y16 = 540422489,
+ YV12 = 842094169,
+ DEPTH_16 = 48,
+ DEPTH_24 = 49,
+ DEPTH_24_STENCIL_8 = 50,
+ DEPTH_32F = 51,
+ DEPTH_32F_STENCIL_8 = 52,
+ STENCIL_8 = 53,
+ YCBCR_P010 = 54,
+ HSV_888 = 55,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayout.aidl
new file mode 100644
index 0000000..8bca42f
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayout.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable PlaneLayout {
+ android.hardware.graphics.common.PlaneLayoutComponent[] components;
+ long offsetInBytes;
+ long sampleIncrementInBits;
+ long strideInBytes;
+ long widthInSamples;
+ long heightInSamples;
+ long totalSizeInBytes;
+ long horizontalSubsampling;
+ long verticalSubsampling;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayoutComponent.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayoutComponent.aidl
new file mode 100644
index 0000000..f5a649c
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayoutComponent.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable PlaneLayoutComponent {
+ android.hardware.graphics.common.ExtendableType type;
+ long offsetInBits;
+ long sizeInBits;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayoutComponentType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
new file mode 100644
index 0000000..7ff8d76
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
@@ -0,0 +1,29 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum PlaneLayoutComponentType {
+ Y = 1,
+ CB = 2,
+ CR = 4,
+ R = 1024,
+ G = 2048,
+ B = 4096,
+ RAW = 1048576,
+ A = 1073741824,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Rect.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Rect.aidl
new file mode 100644
index 0000000..e0ba69b
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Rect.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable Rect {
+ int left;
+ int top;
+ int right;
+ int bottom;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Smpte2086.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Smpte2086.aidl
new file mode 100644
index 0000000..5da36f6
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/Smpte2086.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable Smpte2086 {
+ android.hardware.graphics.common.XyColor primaryRed;
+ android.hardware.graphics.common.XyColor primaryGreen;
+ android.hardware.graphics.common.XyColor primaryBlue;
+ android.hardware.graphics.common.XyColor whitePoint;
+ float maxLuminance;
+ float minLuminance;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/StandardMetadataType.aidl
new file mode 100644
index 0000000..34b53a2
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum StandardMetadataType {
+ INVALID = 0,
+ BUFFER_ID = 1,
+ NAME = 2,
+ WIDTH = 3,
+ HEIGHT = 4,
+ LAYER_COUNT = 5,
+ PIXEL_FORMAT_REQUESTED = 6,
+ PIXEL_FORMAT_FOURCC = 7,
+ PIXEL_FORMAT_MODIFIER = 8,
+ USAGE = 9,
+ ALLOCATION_SIZE = 10,
+ PROTECTED_CONTENT = 11,
+ COMPRESSION = 12,
+ INTERLACED = 13,
+ CHROMA_SITING = 14,
+ PLANE_LAYOUTS = 15,
+ CROP = 16,
+ DATASPACE = 17,
+ BLEND_MODE = 18,
+ SMPTE2086 = 19,
+ CTA861_3 = 20,
+ SMPTE2094_40 = 21,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/XyColor.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/XyColor.aidl
new file mode 100644
index 0000000..d96d0ac
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1/android/hardware/graphics/common/XyColor.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable XyColor {
+ float x;
+ float y;
+}
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 5f1ed63..dafbbf9 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -43,5 +43,5 @@
"android.hardware.graphics.composer@2.1-command-buffer",
],
disable_framework: true,
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
index 0d7e86f..efe6dad 100644
--- a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -1,6 +1,4 @@
service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service
- interface android.hardware.graphics.composer@2.1::IComposer default
- interface android.hardware.graphics.composer@2.2::IComposer default
class hal animation
user system
group graphics drmrpc
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index e38af00..e1a254d 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -61,6 +61,6 @@
disable_framework: true,
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index fa4823e..18ea2aa 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -50,5 +50,5 @@
"android.hardware.graphics.composer@2.3-command-buffer",
],
disable_framework: true,
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index 937af3d..9e7cc46 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -52,5 +52,5 @@
"android.hardware.graphics.composer@2.4-command-buffer",
],
disable_framework: true,
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index a055b61..1f7ae04 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -24,5 +24,5 @@
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.0-vts",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/graphics/mapper/2.1/vts/functional/Android.bp b/graphics/mapper/2.1/vts/functional/Android.bp
index bb76c74..ccbe40f 100644
--- a/graphics/mapper/2.1/vts/functional/Android.bp
+++ b/graphics/mapper/2.1/vts/functional/Android.bp
@@ -26,5 +26,5 @@
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1-vts",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/graphics/mapper/3.0/vts/functional/Android.bp b/graphics/mapper/3.0/vts/functional/Android.bp
index f01670e..3f4abec 100644
--- a/graphics/mapper/3.0/vts/functional/Android.bp
+++ b/graphics/mapper/3.0/vts/functional/Android.bp
@@ -26,5 +26,5 @@
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@3.0-vts",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/graphics/mapper/4.0/vts/functional/Android.bp b/graphics/mapper/4.0/vts/functional/Android.bp
index 3542a6e..03abc89 100644
--- a/graphics/mapper/4.0/vts/functional/Android.bp
+++ b/graphics/mapper/4.0/vts/functional/Android.bp
@@ -36,6 +36,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 0689919..8247ded 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -107,7 +107,7 @@
ASSERT_NO_FATAL_FAILURE(decode(descriptorInfo, vec));
}
- void verifyDummyDescriptorInfoPlaneLayouts(const std::vector<PlaneLayout>& planeLayouts) {
+ void verifyRGBA8888PlaneLayouts(const std::vector<PlaneLayout>& planeLayouts) {
ASSERT_EQ(1, planeLayouts.size());
const auto& planeLayout = planeLayouts.front();
@@ -191,7 +191,7 @@
}
void getAndroidYCbCr(const native_handle_t* bufferHandle, uint8_t* data,
- android_ycbcr* outYCbCr) {
+ android_ycbcr* outYCbCr, int64_t* hSubsampling, int64_t* vSubsampling) {
hidl_vec<uint8_t> vec;
ASSERT_EQ(Error::NONE,
mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
@@ -241,6 +241,14 @@
ASSERT_EQ(outYCbCr->chroma_step, sampleIncrementInBytes);
}
+ if (*hSubsampling == 0 && *vSubsampling == 0) {
+ *hSubsampling = planeLayout.horizontalSubsampling;
+ *vSubsampling = planeLayout.verticalSubsampling;
+ } else {
+ ASSERT_EQ(*hSubsampling, planeLayout.horizontalSubsampling);
+ ASSERT_EQ(*vSubsampling, planeLayout.verticalSubsampling);
+ }
+
if (type == PlaneLayoutComponentType::CB) {
ASSERT_EQ(nullptr, outYCbCr->cb);
outYCbCr->cb = tmpData;
@@ -268,8 +276,16 @@
}
}
- void verifyRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes,
- uint32_t seed = 0) {
+ void verifyRGBA8888(const native_handle_t* bufferHandle, uint8_t* data, uint32_t height,
+ size_t strideInBytes, size_t widthInBytes, uint32_t seed = 0) {
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(Error::NONE,
+ mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+ std::vector<PlaneLayout> planeLayouts;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+ verifyRGBA8888PlaneLayouts(planeLayouts);
+
for (uint32_t y = 0; y < height; y++) {
for (size_t i = 0; i < widthInBytes; i++) {
EXPECT_EQ(static_cast<uint8_t>(y + seed), data[i]);
@@ -534,7 +550,9 @@
// lock again for reading
ASSERT_NO_FATAL_FAILURE(
data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
- ASSERT_NO_FATAL_FAILURE(verifyRGBA8888(data, info.height, stride * 4, info.width * 4));
+
+ ASSERT_NO_FATAL_FAILURE(
+ verifyRGBA8888(bufferHandle, data, info.height, stride * 4, info.width * 4));
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
if (fence >= 0) {
@@ -542,9 +560,9 @@
}
}
-TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_420_888) {
+TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
auto info = mDummyDescriptorInfo;
- info.format = PixelFormat::YCBCR_420_888;
+ info.format = PixelFormat::YCRCB_420_SP;
const native_handle_t* bufferHandle;
uint32_t stride;
@@ -560,7 +578,10 @@
data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
android_ycbcr yCbCr;
- ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(bufferHandle, data, &yCbCr));
+ int64_t hSubsampling = 0;
+ int64_t vSubsampling = 0;
+ ASSERT_NO_FATAL_FAILURE(
+ getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
auto yData = static_cast<uint8_t*>(yCbCr.y);
auto cbData = static_cast<uint8_t*>(yCbCr.cb);
@@ -570,6 +591,10 @@
auto chromaStep = yCbCr.chroma_step;
constexpr uint32_t kCbCrSubSampleFactor = 2;
+ ASSERT_EQ(crData + 1, cbData);
+ ASSERT_EQ(2, chromaStep);
+ ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
+ ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
for (uint32_t y = 0; y < info.height; y++) {
for (uint32_t x = 0; x < info.width; x++) {
@@ -577,13 +602,15 @@
yData[yStride * y + x] = val;
- if (y % kCbCrSubSampleFactor && x % kCbCrSubSampleFactor == 0) {
- uint32_t subSampleX = x / kCbCrSubSampleFactor;
- uint32_t subSampleY = y / kCbCrSubSampleFactor;
- auto subSampleVal = static_cast<uint8_t>(info.height * subSampleY + subSampleX);
+ if (y % vSubsampling == 0 && x % hSubsampling == 0) {
+ uint32_t subSampleX = x / hSubsampling;
+ uint32_t subSampleY = y / vSubsampling;
+ const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
+ const auto subSampleVal =
+ static_cast<uint8_t>(info.height * subSampleY + subSampleX);
- cbData[cStride * subSampleY + chromaStep * subSampleX] = subSampleVal;
- crData[cStride * subSampleY + chromaStep * subSampleX] = subSampleVal;
+ cbData[subSampleOffset] = subSampleVal;
+ crData[subSampleOffset] = subSampleVal + 1;
}
}
}
@@ -594,24 +621,28 @@
ASSERT_NO_FATAL_FAILURE(
data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
- ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(bufferHandle, data, &yCbCr));
+ ASSERT_NO_FATAL_FAILURE(
+ getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
yData = static_cast<uint8_t*>(yCbCr.y);
cbData = static_cast<uint8_t*>(yCbCr.cb);
crData = static_cast<uint8_t*>(yCbCr.cr);
+
for (uint32_t y = 0; y < info.height; y++) {
for (uint32_t x = 0; x < info.width; x++) {
auto val = static_cast<uint8_t>(info.height * y + x);
EXPECT_EQ(val, yData[yStride * y + x]);
- if (y % kCbCrSubSampleFactor == 0 && x % kCbCrSubSampleFactor == 0) {
- uint32_t subSampleX = x / kCbCrSubSampleFactor;
- uint32_t subSampleY = y / kCbCrSubSampleFactor;
- auto subSampleVal = static_cast<uint8_t>(info.height * subSampleY + subSampleX);
+ if (y % vSubsampling == 0 && x % hSubsampling == 0) {
+ uint32_t subSampleX = x / hSubsampling;
+ uint32_t subSampleY = y / vSubsampling;
+ const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
+ const auto subSampleVal =
+ static_cast<uint8_t>(info.height * subSampleY + subSampleX);
- EXPECT_EQ(subSampleVal, cbData[cStride * subSampleY + chromaStep * subSampleX]);
- EXPECT_EQ(subSampleVal, crData[cStride * subSampleY + chromaStep * subSampleX]);
+ EXPECT_EQ(subSampleVal, cbData[subSampleOffset]);
+ EXPECT_EQ(subSampleVal + 1, crData[subSampleOffset]);
}
}
}
@@ -744,7 +775,8 @@
ASSERT_NO_FATAL_FAILURE(mGralloc->rereadLockedBuffer(readBufferHandle));
- ASSERT_NO_FATAL_FAILURE(verifyRGBA8888(readData, info.height, stride * 4, info.width * 4));
+ ASSERT_NO_FATAL_FAILURE(
+ verifyRGBA8888(readBufferHandle, readData, info.height, stride * 4, info.width * 4));
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(readBufferHandle));
if (fence >= 0) {
@@ -1005,7 +1037,7 @@
std::vector<PlaneLayout> planeLayouts;
ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
- ASSERT_NO_FATAL_FAILURE(verifyDummyDescriptorInfoPlaneLayouts(planeLayouts));
+ ASSERT_NO_FATAL_FAILURE(verifyRGBA8888PlaneLayouts(planeLayouts));
}
/**
@@ -1870,7 +1902,7 @@
if (ret == Error::NONE) {
std::vector<PlaneLayout> planeLayouts;
ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
- ASSERT_NO_FATAL_FAILURE(verifyDummyDescriptorInfoPlaneLayouts(planeLayouts));
+ ASSERT_NO_FATAL_FAILURE(verifyRGBA8888PlaneLayouts(planeLayouts));
} else {
ASSERT_EQ(Error::UNSUPPORTED, ret);
}
diff --git a/health/1.0/vts/functional/Android.bp b/health/1.0/vts/functional/Android.bp
index be2d206..f4a04a7 100644
--- a/health/1.0/vts/functional/Android.bp
+++ b/health/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalHealthV1_0TargetTest.cpp"],
static_libs: ["android.hardware.health@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/health/2.0/vts/functional/Android.bp b/health/2.0/vts/functional/Android.bp
index 43571ef..ab14ca7 100644
--- a/health/2.0/vts/functional/Android.bp
+++ b/health/2.0/vts/functional/Android.bp
@@ -23,5 +23,5 @@
"android.hardware.health@1.0",
"android.hardware.health@2.0",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index 352a990..441e2d7 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -16,11 +16,15 @@
#define LOG_TAG "health_hidl_hal_test"
+#include <chrono>
#include <mutex>
#include <set>
#include <string>
+#include <thread>
#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/hardware/health/1.0/types.h>
#include <android/hardware/health/2.0/IHealth.h>
#include <android/hardware/health/2.0/types.h>
#include <gflags/gflags.h>
@@ -32,48 +36,25 @@
using ::testing::AssertionFailure;
using ::testing::AssertionResult;
using ::testing::AssertionSuccess;
+using namespace std::chrono_literals;
DEFINE_bool(force, false, "Force test healthd even when the default instance is present.");
-// If GTEST_SKIP is not implemented, use our own skipping mechanism
-#ifndef GTEST_SKIP
-static std::mutex gSkippedTestsMutex;
-static std::set<std::string> gSkippedTests;
-static std::string GetCurrentTestName() {
- const auto& info = ::testing::UnitTest::GetInstance()->current_test_info();
-#ifdef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- std::string test_suite = info->test_suite_name();
-#else
- std::string test_suite = info->test_case_name();
-#endif
- return test_suite + "." + info->name();
-}
-
-#define GTEST_SKIP() \
- do { \
- std::unique_lock<std::mutex> lock(gSkippedTestsMutex); \
- gSkippedTests.insert(GetCurrentTestName()); \
- return; \
+// Return expr if it is evaluated to false.
+#define TEST_AND_RETURN(expr) \
+ do { \
+ auto res = (expr); \
+ if (!res) return res; \
} while (0)
-#define SKIP_IF_SKIPPED() \
- do { \
- std::unique_lock<std::mutex> lock(gSkippedTestsMutex); \
- if (gSkippedTests.find(GetCurrentTestName()) != gSkippedTests.end()) { \
- std::cerr << "[ SKIPPED ] " << GetCurrentTestName() << std::endl; \
- return; \
- } \
- } while (0)
-#else
-#define SKIP_IF_SKIPPED()
-#endif
-
namespace android {
namespace hardware {
namespace health {
-namespace V2_0 {
using V1_0::BatteryStatus;
+using V1_0::toString;
+
+namespace V2_0 {
class HealthHidlTest : public ::testing::TestWithParam<std::string> {
public:
@@ -141,7 +122,6 @@
* unregisterCallback, and update.
*/
TEST_P(HealthHidlTest, Callbacks) {
- SKIP_IF_SKIPPED();
using namespace std::chrono_literals;
sp<Callback> firstCallback = new Callback();
sp<Callback> secondCallback = new Callback();
@@ -178,7 +158,6 @@
}
TEST_P(HealthHidlTest, UnregisterNonExistentCallback) {
- SKIP_IF_SKIPPED();
sp<Callback> callback = new Callback();
auto ret = mHealth->unregisterCallback(callback);
ASSERT_OK(ret);
@@ -263,7 +242,6 @@
* Tests the values returned by getChargeCounter() from interface IHealth.
*/
TEST_P(HealthHidlTest, getChargeCounter) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
}));
@@ -273,7 +251,6 @@
* Tests the values returned by getCurrentNow() from interface IHealth.
*/
TEST_P(HealthHidlTest, getCurrentNow) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
}));
@@ -283,7 +260,6 @@
* Tests the values returned by getCurrentAverage() from interface IHealth.
*/
TEST_P(HealthHidlTest, getCurrentAverage) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
}));
@@ -293,7 +269,6 @@
* Tests the values returned by getCapacity() from interface IHealth.
*/
TEST_P(HealthHidlTest, getCapacity) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
}));
@@ -303,7 +278,6 @@
* Tests the values returned by getEnergyCounter() from interface IHealth.
*/
TEST_P(HealthHidlTest, getEnergyCounter) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
}));
@@ -313,7 +287,6 @@
* Tests the values returned by getChargeStatus() from interface IHealth.
*/
TEST_P(HealthHidlTest, getChargeStatus) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyEnum<BatteryStatus>(value));
}));
@@ -323,7 +296,6 @@
* Tests the values returned by getStorageInfo() from interface IHealth.
*/
TEST_P(HealthHidlTest, getStorageInfo) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
}));
@@ -333,7 +305,6 @@
* Tests the values returned by getDiskStats() from interface IHealth.
*/
TEST_P(HealthHidlTest, getDiskStats) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
}));
@@ -343,7 +314,6 @@
* Tests the values returned by getHealthInfo() from interface IHealth.
*/
TEST_P(HealthHidlTest, getHealthInfo) {
- SKIP_IF_SKIPPED();
EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
}));
@@ -353,6 +323,357 @@
PerInstance, HealthHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
android::hardware::PrintInstanceNameToString);
+
+// For battery current tests, value may not be stable if the battery current has fluctuated.
+// Retry in a bit more time (with the following timeout) and consider the test successful if it
+// has succeed once.
+static constexpr auto gBatteryTestTimeout = 1min;
+// Tests on battery current signs are only enforced on devices launching with Android 11.
+static constexpr int64_t gBatteryTestMinShippingApiLevel = 30;
+static constexpr double gCurrentCompareFactor = 0.50;
+
+// Tuple for all IHealth::get* API return values.
+template <typename T>
+struct HalResult {
+ Result result;
+ T value;
+};
+
+// Needs to be called repeatedly within a period of time to ensure values are initialized.
+static AssertionResult IsBatteryCurrentSignCorrect(HalResult<BatteryStatus> status,
+ HalResult<int32_t> current,
+ bool acceptZeroCurrentAsUnknown) {
+ // getChargeStatus / getCurrentNow / getCurrentAverage / getHealthInfo already tested above.
+ // Here, just skip if not ok.
+ if (status.result != Result::SUCCESS) {
+ return AssertionSuccess() << "getChargeStatus / getHealthInfo returned "
+ << toString(status.result) << ", skipping";
+ }
+
+ if (current.result != Result::SUCCESS) {
+ return AssertionSuccess() << "getCurrentNow / getCurrentAverage returned "
+ << toString(current.result) << ", skipping";
+ }
+
+ // For IHealth.getCurrentNow/Average, if current is not available, it is expected that
+ // current.result == Result::NOT_SUPPORTED, which is checked above. Hence, zero current is
+ // not treated as unknown values.
+ // For IHealth.getHealthInfo, if current is not available, health_info.current_* == 0.
+ // Caller of this function provides current.result == Result::SUCCESS. Hence, just skip the
+ // check.
+ if (current.value == 0 && acceptZeroCurrentAsUnknown) {
+ return AssertionSuccess()
+ << "current is 0, which indicates the value may not be available. Skipping.";
+ }
+
+ switch (status.value) {
+ case BatteryStatus::UNKNOWN:
+ if (current.value != 0) {
+ // BatteryStatus may be UNKNOWN initially with a non-zero current value, but
+ // after it is initialized, it should be known.
+ return AssertionFailure()
+ << "BatteryStatus is UNKNOWN but current is not 0. Actual: "
+ << current.value;
+ }
+ break;
+ case BatteryStatus::CHARGING:
+ if (current.value <= 0) {
+ return AssertionFailure()
+ << "BatteryStatus is CHARGING but current is not positive. Actual: "
+ << current.value;
+ }
+ break;
+ case BatteryStatus::NOT_CHARGING:
+ if (current.value > 0) {
+ return AssertionFailure() << "BatteryStatus is " << toString(status.value)
+ << " but current is positive. Actual: " << current.value;
+ }
+ break;
+ case BatteryStatus::DISCHARGING:
+ if (current.value >= 0) {
+ return AssertionFailure()
+ << "BatteryStatus is " << toString(status.value)
+ << " but current is not negative. Actual: " << current.value;
+ }
+ break;
+ case BatteryStatus::FULL:
+ // Battery current may be positive or negative depending on the load.
+ break;
+ default:
+ return AssertionFailure() << "Unknown BatteryStatus " << toString(status.value);
+ }
+
+ return AssertionSuccess() << "BatteryStatus is " << toString(status.value)
+ << " and current has the correct sign: " << current.value;
+}
+
+static AssertionResult IsValueSimilar(int32_t dividend, int32_t divisor, double factor) {
+ auto difference = abs(dividend - divisor);
+ if (difference > factor * abs(divisor)) {
+ return AssertionFailure() << dividend << " and " << divisor << " are not similar.";
+ }
+ return AssertionSuccess() << dividend << " and " << divisor << " are similar.";
+}
+
+static AssertionResult IsBatteryCurrentSimilar(HalResult<BatteryStatus> status,
+ HalResult<int32_t> currentNow,
+ HalResult<int32_t> currentAverage) {
+ if (status.result == Result::SUCCESS && status.value == BatteryStatus::FULL) {
+ // No reason to test on full battery because battery current load fluctuates.
+ return AssertionSuccess() << "Battery is full, skipping";
+ }
+
+ // getCurrentNow / getCurrentAverage / getHealthInfo already tested above. Here, just skip if
+ // not SUCCESS or value 0.
+ if (currentNow.result != Result::SUCCESS || currentNow.value == 0) {
+ return AssertionSuccess() << "getCurrentNow returned " << toString(currentNow.result)
+ << " with value " << currentNow.value << ", skipping";
+ }
+
+ if (currentAverage.result != Result::SUCCESS || currentAverage.value == 0) {
+ return AssertionSuccess() << "getCurrentAverage returned "
+ << toString(currentAverage.result) << " with value "
+ << currentAverage.value << ", skipping";
+ }
+
+ // Check that the two values are similar. Note that the two tests uses a different
+ // divisor to ensure that they are actually pretty similar. For example,
+ // IsValueSimilar(5,10,0.4) returns true, but IsValueSimlar(10,5,0.4) returns false.
+ TEST_AND_RETURN(IsValueSimilar(currentNow.value, currentAverage.value, gCurrentCompareFactor)
+ << " for now vs. average. Check units.");
+ TEST_AND_RETURN(IsValueSimilar(currentAverage.value, currentNow.value, gCurrentCompareFactor)
+ << " for average vs. now. Check units.");
+ return AssertionSuccess() << "currentNow = " << currentNow.value
+ << " and currentAverage = " << currentAverage.value
+ << " are considered similar.";
+}
+
+// Test that f() returns AssertionSuccess() once in a given period of time.
+template <typename Duration, typename Function>
+static AssertionResult SucceedOnce(Duration d, Function f) {
+ AssertionResult result = AssertionFailure() << "Function never evaluated.";
+ auto end = std::chrono::system_clock::now() + d;
+ while (std::chrono::system_clock::now() <= end) {
+ result = f();
+ if (result) {
+ return result;
+ }
+ std::this_thread::sleep_for(2s);
+ }
+ return result;
+}
+
+uint64_t GetShippingApiLevel() {
+ uint64_t api_level = android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
+ if (api_level != 0) {
+ return api_level;
+ }
+ return android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
+}
+
+class BatteryTest : public HealthHidlTest {
+ public:
+ void SetUp() override {
+ HealthHidlTest::SetUp();
+
+ auto shippingApiLevel = GetShippingApiLevel();
+ if (shippingApiLevel < gBatteryTestMinShippingApiLevel) {
+ GTEST_SKIP() << "Skipping on devices with first API level " << shippingApiLevel;
+ }
+ }
+};
+
+TEST_P(BatteryTest, InstantCurrentAgainstChargeStatusInHealthInfo) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<HealthInfo> healthInfo;
+ TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
+ healthInfo = {result, value};
+ })));
+
+ return IsBatteryCurrentSignCorrect(
+ {healthInfo.result, healthInfo.value.legacy.batteryStatus},
+ {healthInfo.result, healthInfo.value.legacy.batteryCurrent},
+ true /* accept zero current as unknown */);
+ };
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when current_now becomes stable.";
+}
+
+TEST_P(BatteryTest, AverageCurrentAgainstChargeStatusInHealthInfo) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<HealthInfo> healthInfo;
+ TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
+ healthInfo = {result, value};
+ })));
+ return IsBatteryCurrentSignCorrect(
+ {healthInfo.result, healthInfo.value.legacy.batteryStatus},
+ {healthInfo.result, healthInfo.value.batteryCurrentAverage},
+ true /* accept zero current as unknown */);
+ };
+
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when current_average becomes stable.";
+}
+
+TEST_P(BatteryTest, InstantCurrentAgainstAverageCurrentInHealthInfo) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<HealthInfo> healthInfo;
+ TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
+ healthInfo = {result, value};
+ })));
+ return IsBatteryCurrentSimilar({healthInfo.result, healthInfo.value.legacy.batteryStatus},
+ {healthInfo.result, healthInfo.value.legacy.batteryCurrent},
+ {healthInfo.result, healthInfo.value.batteryCurrentAverage});
+ };
+
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when current_now and current_average becomes "
+ "stable.";
+}
+
+TEST_P(BatteryTest, InstantCurrentAgainstChargeStatusFromHal) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<BatteryStatus> status;
+ HalResult<int32_t> currentNow;
+ TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
+ status = {result, value};
+ })));
+ TEST_AND_RETURN(isOk(mHealth->getCurrentNow([&](auto result, auto value) {
+ currentNow = {result, value};
+ })));
+
+ return IsBatteryCurrentSignCorrect(status, currentNow,
+ false /* accept zero current as unknown */);
+ };
+
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when current_now becomes stable.";
+}
+
+TEST_P(BatteryTest, AverageCurrentAgainstChargeStatusFromHal) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<BatteryStatus> status;
+ TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
+ status = {result, value};
+ })));
+ HalResult<int32_t> currentAverage;
+ TEST_AND_RETURN(isOk(mHealth->getCurrentAverage([&](auto result, auto value) {
+ currentAverage = {result, value};
+ })));
+ return IsBatteryCurrentSignCorrect(status, currentAverage,
+ false /* accept zero current as unknown */);
+ };
+
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when current_average becomes stable.";
+}
+
+TEST_P(BatteryTest, InstantCurrentAgainstAverageCurrentFromHal) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<BatteryStatus> status;
+ TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
+ status = {result, value};
+ })));
+ HalResult<int32_t> currentNow;
+ TEST_AND_RETURN(isOk(mHealth->getCurrentNow([&](auto result, auto value) {
+ currentNow = {result, value};
+ })));
+ HalResult<int32_t> currentAverage;
+ TEST_AND_RETURN(isOk(mHealth->getCurrentAverage([&](auto result, auto value) {
+ currentAverage = {result, value};
+ })));
+ return IsBatteryCurrentSimilar(status, currentNow, currentAverage);
+ };
+
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when current_average becomes stable.";
+}
+
+AssertionResult IsBatteryStatusCorrect(HalResult<BatteryStatus> status,
+ HalResult<HealthInfo> healthInfo) {
+ // getChargetStatus / getHealthInfo is already tested above. Here, just skip if not ok.
+ if (healthInfo.result != Result::SUCCESS) {
+ return AssertionSuccess() << "getHealthInfo returned " << toString(healthInfo.result)
+ << ", skipping";
+ }
+ if (status.result != Result::SUCCESS) {
+ return AssertionSuccess() << "getChargeStatus returned " << toString(status.result)
+ << ", skipping";
+ }
+
+ const auto& batteryInfo = healthInfo.value.legacy;
+ bool isConnected = batteryInfo.chargerAcOnline || batteryInfo.chargerUsbOnline ||
+ batteryInfo.chargerWirelessOnline;
+
+ std::stringstream message;
+ message << "BatteryStatus is " << toString(status.value) << " and "
+ << (isConnected ? "" : "no ")
+ << "power source is connected: ac=" << batteryInfo.chargerAcOnline
+ << ", usb=" << batteryInfo.chargerUsbOnline
+ << ", wireless=" << batteryInfo.chargerWirelessOnline;
+
+ switch (status.value) {
+ case BatteryStatus::UNKNOWN: {
+ // Don't enforce anything on isConnected on unknown battery status.
+ // Battery-less devices must report UNKNOWN battery status, but may report true
+ // or false on isConnected.
+ } break;
+ case BatteryStatus::CHARGING:
+ case BatteryStatus::NOT_CHARGING:
+ case BatteryStatus::FULL: {
+ if (!isConnected) {
+ return AssertionFailure() << message.str();
+ }
+ } break;
+ case BatteryStatus::DISCHARGING: {
+ if (isConnected) {
+ return AssertionFailure() << message.str();
+ }
+ } break;
+ default: {
+ return AssertionFailure() << "Unknown battery status value " << toString(status.value);
+ } break;
+ }
+
+ return AssertionSuccess() << message.str();
+}
+
+TEST_P(BatteryTest, ConnectedAgainstStatusFromHal) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<BatteryStatus> status;
+ TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
+ status = {result, value};
+ })));
+ HalResult<HealthInfo> healthInfo;
+ TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
+ healthInfo = {result, value};
+ })));
+ return IsBatteryStatusCorrect(status, healthInfo);
+ };
+
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when battery_status becomes stable.";
+}
+
+TEST_P(BatteryTest, ConnectedAgainstStatusInHealthInfo) {
+ auto testOnce = [&]() -> AssertionResult {
+ HalResult<HealthInfo> healthInfo;
+ TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
+ healthInfo = {result, value};
+ })));
+ return IsBatteryStatusCorrect({healthInfo.result, healthInfo.value.legacy.batteryStatus},
+ healthInfo);
+ };
+
+ EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+ << "You may want to try again later when getHealthInfo becomes stable.";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, BatteryTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
} // namespace V2_0
} // namespace health
} // namespace hardware
diff --git a/health/2.1/vts/functional/Android.bp b/health/2.1/vts/functional/Android.bp
index 17472fa..7894ca2 100644
--- a/health/2.1/vts/functional/Android.bp
+++ b/health/2.1/vts/functional/Android.bp
@@ -27,6 +27,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index 4c703c5..2201031 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -24,7 +24,7 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
test_config: "VtsHalHealthStorageV1_0TargetTest.config",
}
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index 72b19a1..7298c7d 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -18,4 +18,5 @@
},
},
},
+ versions: ["1"],
}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/.hash b/identity/aidl/aidl_api/android.hardware.identity/1/.hash
new file mode 100644
index 0000000..1e9516f
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/.hash
@@ -0,0 +1 @@
+5f61a54bc37f935e7eb8d1fb624347f68c03c6ca
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/Certificate.aidl b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/Certificate.aidl
new file mode 100644
index 0000000..7e3002d
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/Certificate.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable Certificate {
+ byte[] encodedCertificate;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/CipherSuite.aidl b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/CipherSuite.aidl
new file mode 100644
index 0000000..447203f
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/CipherSuite.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@Backing(type="int") @VintfStability
+enum CipherSuite {
+ CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1,
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/HardwareInformation.aidl
new file mode 100644
index 0000000..e1296e0
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/HardwareInformation.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable HardwareInformation {
+ @utf8InCpp String credentialStoreName;
+ @utf8InCpp String credentialStoreAuthorName;
+ int dataChunkSize;
+ boolean isDirectAccess;
+ @utf8InCpp String[] supportedDocTypes;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IIdentityCredential.aidl
new file mode 100644
index 0000000..58b90b5
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IIdentityCredential.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IIdentityCredential {
+ byte[] deleteCredential();
+ byte[] createEphemeralKeyPair();
+ void setReaderEphemeralPublicKey(in byte[] publicKey);
+ long createAuthChallenge();
+ void startRetrieval(in android.hardware.identity.SecureAccessControlProfile[] accessControlProfiles, in android.hardware.keymaster.HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob, in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
+ void startRetrieveEntryValue(in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize, in int[] accessControlProfileIds);
+ byte[] retrieveEntryValue(in byte[] encryptedContent);
+ void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
+ android.hardware.identity.Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IIdentityCredentialStore.aidl
new file mode 100644
index 0000000..5dafb76
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -0,0 +1,37 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IIdentityCredentialStore {
+ android.hardware.identity.HardwareInformation getHardwareInformation();
+ android.hardware.identity.IWritableIdentityCredential createCredential(in @utf8InCpp String docType, in boolean testCredential);
+ android.hardware.identity.IIdentityCredential getCredential(in android.hardware.identity.CipherSuite cipherSuite, in byte[] credentialData);
+ const int STATUS_OK = 0;
+ const int STATUS_FAILED = 1;
+ const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
+ const int STATUS_INVALID_DATA = 3;
+ const int STATUS_INVALID_AUTH_TOKEN = 4;
+ const int STATUS_INVALID_ITEMS_REQUEST_MESSAGE = 5;
+ const int STATUS_READER_SIGNATURE_CHECK_FAILED = 6;
+ const int STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 7;
+ const int STATUS_USER_AUTHENTICATION_FAILED = 8;
+ const int STATUS_READER_AUTHENTICATION_FAILED = 9;
+ const int STATUS_NO_ACCESS_CONTROL_PROFILES = 10;
+ const int STATUS_NOT_IN_REQUEST_MESSAGE = 11;
+ const int STATUS_SESSION_TRANSCRIPT_MISMATCH = 12;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IWritableIdentityCredential.aidl
new file mode 100644
index 0000000..32f283c
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IWritableIdentityCredential {
+ android.hardware.identity.Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge);
+ void startPersonalization(in int accessControlProfileCount, in int[] entryCounts);
+ android.hardware.identity.SecureAccessControlProfile addAccessControlProfile(in int id, in android.hardware.identity.Certificate readerCertificate, in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
+ void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize);
+ byte[] addEntryValue(in byte[] content);
+ void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/SecureAccessControlProfile.aidl
new file mode 100644
index 0000000..dfc1ad0
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/1/android/hardware/identity/SecureAccessControlProfile.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable SecureAccessControlProfile {
+ int id;
+ android.hardware.identity.Certificate readerCertificate;
+ boolean userAuthenticationRequired;
+ long timeoutMillis;
+ long secureUserId;
+ byte[] mac;
+}
diff --git a/identity/aidl/android/hardware/identity/CipherSuite.aidl b/identity/aidl/android/hardware/identity/CipherSuite.aidl
index 20b02a8..f38134b 100644
--- a/identity/aidl/android/hardware/identity/CipherSuite.aidl
+++ b/identity/aidl/android/hardware/identity/CipherSuite.aidl
@@ -24,13 +24,15 @@
enum CipherSuite {
/**
* Specifies that the cipher suite that will be used to secure communications between the reader
- * is:
+ * and the prover is using the following primitives
*
- * - ECDHE with HKDF-SHA-256 for key agreement.
- * - AES-256 with GCM block mode for authenticated encryption (nonces are incremented by
- * one for every message).
- * - ECDSA with SHA-256 for signing (used for signing session transcripts to defeat
- * man-in-the-middle attacks), signing keys are not ephemeral.
+ * - ECKA-DH (Elliptic Curve Key Agreement Algorithm - Diffie-Hellman, see BSI TR-03111)
+ * - HKDF-SHA-256 (see RFC 5869)
+ * - AES-256-GCM (see NIST SP 800-38D)
+ * - HMAC-SHA-256 (see RFC 2104)
+ *
+ * The exact way these primitives are combined to derive the session key is specified in
+ * section 9.2.1.4 of ISO/IEC 18013-5 (see description of cipher suite '1').
*
* At present this is the only supported cipher suite and it is mandatory for all
* implementations to support it.
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index cc14271..7d14f03 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -48,6 +48,8 @@
* with the reader. The reason for generating the key pair in the secure environment is so that
* the secure environment knows what public key to expect to find in the session transcript.
*
+ * The generated key must be an EC key using the P-256 curve.
+ *
* This method may only be called once per instance. If called more than once, STATUS_FAILED
* will be returned.
*
@@ -61,7 +63,8 @@
* This method may only be called once per instance. If called more than once, STATUS_FAILED
* will be returned.
*
- * @param publicKey contains the reader's ephemeral public key, in uncompressed form.
+ * @param publicKey contains the reader's ephemeral public key, in uncompressed
+ * form (e.g. 0x04 || X || Y).
*/
void setReaderEphemeralPublicKey(in byte[] publicKey);
@@ -82,9 +85,9 @@
* This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
* createAuthChallenge() and before startRetrieveEntry(). This method call is followed by
* multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally
- * finishRetrieval().This whole process is called a "credential presentation".
+ * finishRetrieval().
*
- * It is permissible to perform multiple credential presentations using the same instance (e.g.
+ * It is permissible to perform data retrievals multiple times using the same instance (e.g.
* startRetrieval(), then multiple calls of startRetrieveEntryValue(), retrieveEntryValue(),
* then finally finishRetrieval()) but if this is done, the sessionTranscript parameter
* must be identical for each startRetrieval() invocation. If this is not the case, this call
@@ -148,6 +151,8 @@
* EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub)
* ItemsRequestBytes = #6.24(bstr .cbor ItemsRequest)
*
+ * EReaderKey.Pub = COSE_Key ; Ephemeral public key provided by reader
+ *
* The public key corresponding to the key used to made signature, can be found in the
* 'x5chain' unprotected header element of the COSE_Sign1 structure (as as described
* in 'draft-ietf-cose-x509-04'). There will be at least one certificate in said element
@@ -220,13 +225,11 @@
*
* It is permissible to keep retrieving values if an access control check fails.
*
- * @param nameSpace is the namespace of the element, e.g. "org.iso.18013"
+ * @param nameSpace is the namespace of the element, e.g. "org.iso.18013.5.1"
*
- * @param name is the name of the element.
+ * @param name is the name of the element, e.g. "driving_privileges".
*
- * @param entrySize is the size of the entry value, if it's a text string or a byte string.
- * It must be zero if the entry value is an integer or boolean. If this requirement
- * is not met the call fails with STATUS_INVALID_DATA.
+ * @param entrySize is the size of the entry value encoded in CBOR.
*
* @param accessControlProfileIds specifies the set of access control profiles that can
* authorize access to the provisioned element. If an identifier of a profile
@@ -260,14 +263,12 @@
* @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.
- * The key used for the MAC operation is EMacKey and is derived as follows:
- *
- * KDF(ECDH(SDeviceKey.Priv, EReaderKey.Pub))
- *
- * where SDeviceKey.Priv is the key identified by signingKeyBlob. The KDF
- * and ECDH functions shall be the same as the ciphersuite selected and
- * passed to IIdentityStore.getCredential(). The EMacKey shall be derived
- * using a salt of 0x00.
+ * This code is produced by using the key agreement and key derivation function
+ * from the ciphersuite with the authentication private key and the reader
+ * ephemeral public key to compute a shared message authentication code (MAC)
+ * key, then using the MAC function from the ciphersuite to compute a MAC of
+ * the authenticated data. See section 9.2.3.5 of ISO/IEC 18013-5 for details
+ * of this operation.
*
* DeviceAuthentication = [
* "DeviceAuthentication",
@@ -308,6 +309,34 @@
/**
* Generate a key pair to be used for signing session data and retrieved data items.
*
+ * The generated key must be an EC key using the P-256 curve.
+ *
+ * This method shall return just a single X.509 certificate which is signed by CredentialKey.
+ * When combined with the certificate chain returned at provisioning time by
+ * getAttestationCertificate() on IWritableIdentityCredential (for the credential key), this
+ * forms a chain all the way from the root of trust to the generated key.
+ *
+ * The public part of a signing key is usually included in issuer-signed data and is
+ * used for anti-cloning purposes or as a mechanism for the issuer to attest to data
+ * generated on the device.
+ *
+ * The following non-optional fields for the X.509 certificate shall be set as follows:
+ *
+ * - version: INTEGER 2 (means v3 certificate).
+ *
+ * - serialNumber: INTEGER 1 (fixed value: same on all certs).
+ *
+ * - signature: must be set to ECDSA.
+ *
+ * - subject: CN shall be set to "Android Identity Credential Authentication Key".
+ *
+ * - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
+ * values returned in HardwareInformation.
+ *
+ * - validity: should be from current time and one year in the future.
+ *
+ * - subjectPublicKeyInfo: must contain attested public key.
+ *
* @param out signingKeyBlob contains an encrypted copy of the newly-generated private
* signing key.
*
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
index 23cb1b7..bd664e8 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -55,8 +55,8 @@
*
* - For each namespase, a set of name/value pairs, each with an associated set of access control
* profile IDs. Names are UTF-8 strings of up to 256 bytes in length (most should be much
- * shorter). Values stored must be encoed as valid CBOR (https://tools.ietf.org/html/rfc7049) and
- * the encoeded size is is limited to at most 512 KiB.
+ * shorter). Values stored must be encoded as CBOR (https://tools.ietf.org/html/rfc7049) and
+ * the encoded size is is limited to at most 512 KiB.
*
* - A set of access control profiles, each with a profile ID and a specification of the
* conditions which satisfy the profile's requirements.
@@ -108,12 +108,13 @@
@VintfStability
interface IIdentityCredentialStore {
/**
- * Success.
+ * Success. This is never returned but included for completeness and for use by code
+ * using these statuses for internal use.
*/
const int STATUS_OK = 0;
/**
- * The operation failed. This is used as a generic catch-all for errors that don't belong
+ * The operation failed. This is used as a generic catch-all for errors that don't belong
* in other categories, including memory/resource allocation failures and I/O errors.
*/
const int STATUS_FAILED = 1;
@@ -124,7 +125,7 @@
const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
/**
- * The passed data was invalid. This is a generic catch all for errors that don't belong
+ * The passed data was invalid. This is a generic catch all for errors that don't belong
* in other categories related to parameter validation.
*/
const int STATUS_INVALID_DATA = 3;
@@ -186,16 +187,19 @@
HardwareInformation getHardwareInformation();
/**
- * createCredential creates a new Credential. When a Credential is created, two cryptographic
+ * createCredential creates a new credential. When a credential is created, two cryptographic
* keys are created: StorageKey, an AES key used to secure the externalized Credential
- * contents, and CredentialKeyPair, an EC key pair used to authenticate the store to the IA. In
- * addition, all of the Credential data content is imported and a certificate for the
- * CredentialKeyPair and a signature produced with the CredentialKeyPair are created. These
+ * contents, and CredentialKey, an EC key pair used to authenticate the store to the IA.
+ *
+ * CredentialKey must be an EC key using the P-256 curve.
+ *
+ * In addition, all of the Credential data content is imported and a certificate for the
+ * CredentialKey and a signature produced with the CredentialKey are created. These
* latter values may be checked by an issuing authority to verify that the data was imported
* into secure hardware and that it was imported unmodified.
*
* @param docType is an optional name (may be an empty string) that identifies the type of
- * credential being created, e.g. "org.iso.18013-5.2019.mdl" (the doc type of the ISO
+ * credential being created, e.g. "org.iso.18013.5.1.mDL" (the doc type of the ISO
* driving license standard).
*
* @param testCredential indicates if this is a test store. Test credentials must use an
@@ -213,15 +217,8 @@
* Credential.
*
* The cipher suite used to communicate with the remote verifier must also be specified. Currently
- * only a single cipher-suite is supported and the details of this are as follow:
- *
- * - ECDHE with HKDF-SHA-256 for key agreement.
- * - AES-256 with GCM block mode for authenticated encryption (nonces are incremented by one
- * for every message).
- * - ECDSA with SHA-256 for signing (used for signing session transcripts to defeat
- * man-in-the-middle attacks), signing keys are not ephemeral.
- *
- * Support for other cipher suites may be added in a future version of this HAL.
+ * only a single cipher-suite is supported. Support for other cipher suites may be added in a
+ * future version of this HAL.
*
* This method fails with STATUS_INVALID_DATA if the passed in credentialData cannot be
* decoded or decrypted.
@@ -233,7 +230,7 @@
* return argument of the same name in finishAddingEntries(), in
* IWritableIdentityCredential.
*
- * @return an IIdentityCredential HIDL interface that provides operations on the Credential.
+ * @return an IIdentityCredential interface that provides operations on the Credential.
*/
IIdentityCredential getCredential(in CipherSuite cipherSuite, in byte[] credentialData);
}
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 483b0c7..07486e6 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -60,12 +60,50 @@
* attestationApplicationId.
*
* - The teeEnforced field in the attestation extension must include
- * Tag::IDENTITY_CREDENTIAL_KEY. This tag indicates that the key is an Identity
- * Credential key (which can only sign/MAC very specific messages) and not an Android
- * Keystore key (which can be used to sign/MAC anything).
+ *
+ * - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity
+ * Credential key (which can only sign/MAC very specific messages) and not an Android
+ * Keystore key (which can be used to sign/MAC anything).
+ *
+ * - Tag::PURPOSE must be set to SIGN
+ *
+ * - Tag::KEY_SIZE must be set to the appropriate key size, in bits (e.g. 256)
+ *
+ * - Tag::ALGORITHM must be set to EC
+ *
+ * - Tag::NO_AUTH_REQUIRED must be set
+ *
+ * - Tag::DIGEST must be set to SHA_2_256
+ *
+ * - Tag::EC_CURVE must be set to P_256
*
* Additional authorizations may be needed in the softwareEnforced and teeEnforced
- * fields - the above is not an exhaustive list.
+ * fields - the above is not an exhaustive list. Specifically, authorizations containing
+ * information about the root of trust, OS version, verified boot state, and so on should
+ * be included.
+ *
+ * Since the chain is required to be generated using Keymaster Attestation, the returned
+ * certificate chain has the following properties:
+ *
+ * - The certificate chain is of at least length three.
+ *
+ * - The root of trust is the same as for Keymaster Attestation. This is usually
+ * a certificate owned by Google but depending on the specific Android device it may
+ * be another certificate.
+ *
+ * As with any user of attestation, the Issuing Authority (as a relying party) wishing
+ * to issue a credential to a device using these APIs, must carefully examine the
+ * returned certificate chain for all of the above (and more). In particular, the Issuing
+ * Authority should check the root of trust, verified boot state, patch level,
+ * application id, etc.
+ *
+ * This all depends on the needs of the Issuing Authority and the kind of credential but
+ * in general an Issuing Authority should never issue a credential to a device without
+ * verified boot enabled, to an unrecognized application, or if it appears the device
+ * hasn't been updated for a long time.
+ *
+ * See https://github.com/google/android-key-attestation for an example of how to
+ * examine attestations generated from Android devices.
*
* @param attestationApplicationId is the DER encoded value to be stored
* in Tag::ATTESTATION_APPLICATION_ID. This schema is described in
@@ -102,10 +140,11 @@
* with STATUS_INVALID_DATA.
*
* @param id a numeric identifier that must be unique within the context of a Credential and may
- * be used to reference the profile. If this is not satisfied the call fails with
+ * be used to reference the profile. This id must be non-negative and less than 32 (allowing
+ * for a total of 32 profiles). If this is not satisfied the call fails with
* STATUS_INVALID_DATA.
*
- * @param readerCertificate if non-empty, specifies a X.509 certificate (or chain of
+ * @param readerCertificate if non-empty, specifies a single X.509 certificate (not a chain of
* certificates) that must be used to authenticate requests (see the readerSignature
* parameter in IIdentityCredential.startRetrieval).
*
@@ -142,7 +181,7 @@
* @param accessControlProfileIds specifies the set of access control profiles that can
* authorize access to the provisioned element.
*
- * @param nameSpace is the namespace of the element, e.g. "org.iso.18013"
+ * @param nameSpace is the namespace of the element, e.g. "org.iso.18013.5.1"
*
* @param name is the name of the element.
*
diff --git a/identity/aidl/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/android/hardware/identity/SecureAccessControlProfile.aidl
index 01d312d..13f0c6d 100644
--- a/identity/aidl/android/hardware/identity/SecureAccessControlProfile.aidl
+++ b/identity/aidl/android/hardware/identity/SecureAccessControlProfile.aidl
@@ -29,7 +29,7 @@
/**
* readerCertificate, if non-empty, specifies a single X.509 certificate (not a chain
* of certificates) that must be used to authenticate requests. For details about how
- * this is done, see the readerSignature paremter of IIdentityCredential.startRetrieval.
+ * this is done, see the readerSignature parameter of IIdentityCredential.startRetrieval.
*/
Certificate readerCertificate;
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index 89f7f35..52cd496 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -44,6 +44,8 @@
return false;
}
storageKey_ = random.value();
+ startPersonalizationCalled_ = false;
+ firstEntry_ = true;
return true;
}
@@ -105,6 +107,12 @@
ndk::ScopedAStatus WritableIdentityCredential::startPersonalization(
int32_t accessControlProfileCount, const vector<int32_t>& entryCounts) {
+ if (startPersonalizationCalled_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "startPersonalization called already"));
+ }
+
+ startPersonalizationCalled_ = true;
numAccessControlProfileRemaining_ = accessControlProfileCount;
remainingEntryCounts_ = entryCounts;
entryNameSpace_ = "";
@@ -128,6 +136,19 @@
"numAccessControlProfileRemaining_ is 0 and expected non-zero"));
}
+ if (accessControlProfileIds_.find(id) != accessControlProfileIds_.end()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "Access Control Profile id must be unique"));
+ }
+ accessControlProfileIds_.insert(id);
+
+ if (id < 0 || id >= 32) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "Access Control Profile id must be non-negative and less than 32"));
+ }
+
// Spec requires if |userAuthenticationRequired| is false, then |timeoutMillis| must also
// be zero.
if (!userAuthenticationRequired && timeoutMillis != 0) {
@@ -184,12 +205,20 @@
}
// Handle initial beginEntry() call.
- if (entryNameSpace_ == "") {
+ if (firstEntry_) {
+ firstEntry_ = false;
entryNameSpace_ = nameSpace;
+ allNameSpaces_.insert(nameSpace);
}
// If the namespace changed...
if (nameSpace != entryNameSpace_) {
+ if (allNameSpaces_.find(nameSpace) != allNameSpaces_.end()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "Name space cannot be added in interleaving fashion"));
+ }
+
// Then check that all entries in the previous namespace have been added..
if (remainingEntryCounts_[0] != 0) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -197,6 +226,8 @@
"New namespace but a non-zero number of entries remain to be added"));
}
remainingEntryCounts_.erase(remainingEntryCounts_.begin());
+ remainingEntryCounts_[0] -= 1;
+ allNameSpaces_.insert(nameSpace);
if (signedDataCurrentNamespace_.size() > 0) {
signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
@@ -330,6 +361,18 @@
ndk::ScopedAStatus WritableIdentityCredential::finishAddingEntries(
vector<int8_t>* outCredentialData, vector<int8_t>* outProofOfProvisioningSignature) {
+ if (numAccessControlProfileRemaining_ != 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "numAccessControlProfileRemaining_ is not 0 and expected zero"));
+ }
+
+ if (remainingEntryCounts_.size() > 1 || remainingEntryCounts_[0] != 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "More entry spaces remain than startPersonalization configured"));
+ }
+
if (signedDataCurrentNamespace_.size() > 0) {
signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
}
diff --git a/identity/aidl/default/WritableIdentityCredential.h b/identity/aidl/default/WritableIdentityCredential.h
index b182862..cb91f7b 100644
--- a/identity/aidl/default/WritableIdentityCredential.h
+++ b/identity/aidl/default/WritableIdentityCredential.h
@@ -21,9 +21,11 @@
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
#include <cppbor.h>
+#include <set>
namespace aidl::android::hardware::identity {
+using ::std::set;
using ::std::string;
using ::std::vector;
@@ -66,6 +68,8 @@
// This is set in initialize().
vector<uint8_t> storageKey_;
+ bool startPersonalizationCalled_;
+ bool firstEntry_;
// These are set in getAttestationCertificate().
vector<uint8_t> credentialPrivKey_;
@@ -79,6 +83,9 @@
cppbor::Map signedDataNamespaces_;
cppbor::Array signedDataCurrentNamespace_;
+ // This field is initialized in addAccessControlProfile
+ set<int32_t> accessControlProfileIds_;
+
// These fields are initialized during beginAddEntry()
size_t entryRemainingBytes_;
vector<uint8_t> entryAdditionalData_;
@@ -86,6 +93,7 @@
string entryName_;
vector<int32_t> entryAccessControlProfileIds_;
vector<uint8_t> entryBytes_;
+ set<string> allNameSpaces_;
};
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index cecc814..e4780bf 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -4,7 +4,11 @@
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
],
- srcs: ["VtsHalIdentityTargetTest.cpp"],
+ srcs: [
+ "VtsHalIdentityEndToEndTest.cpp",
+ "VtsIWritableIdentityCredentialTests.cpp",
+ "VtsIdentityTestUtils.cpp",
+ ],
shared_libs: [
"libbinder",
"libcrypto",
@@ -17,6 +21,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/identity/aidl/vts/VtsHalIdentityTargetTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
similarity index 69%
rename from identity/aidl/vts/VtsHalIdentityTargetTest.cpp
rename to identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index ea37fdc..8a4e8a7 100644
--- a/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -28,8 +28,11 @@
#include <future>
#include <map>
+#include "VtsIdentityTestUtils.h"
+
namespace android::hardware::identity {
+using std::endl;
using std::map;
using std::optional;
using std::string;
@@ -41,51 +44,6 @@
using ::android::hardware::keymaster::HardwareAuthToken;
-// ---------------------------------------------------------------------------
-// Test Data.
-// ---------------------------------------------------------------------------
-
-struct TestEntryData {
- TestEntryData(string nameSpace, string name, vector<int32_t> profileIds)
- : nameSpace(nameSpace), name(name), profileIds(profileIds) {}
-
- TestEntryData(string nameSpace, string name, const string& value, vector<int32_t> profileIds)
- : TestEntryData(nameSpace, name, profileIds) {
- valueCbor = cppbor::Tstr(((const char*)value.data())).encode();
- }
- TestEntryData(string nameSpace, string name, const vector<uint8_t>& value,
- vector<int32_t> profileIds)
- : TestEntryData(nameSpace, name, profileIds) {
- valueCbor = cppbor::Bstr(value).encode();
- }
- TestEntryData(string nameSpace, string name, bool value, vector<int32_t> profileIds)
- : TestEntryData(nameSpace, name, profileIds) {
- valueCbor = cppbor::Bool(value).encode();
- }
- TestEntryData(string nameSpace, string name, int64_t value, vector<int32_t> profileIds)
- : TestEntryData(nameSpace, name, profileIds) {
- if (value >= 0) {
- valueCbor = cppbor::Uint(value).encode();
- } else {
- valueCbor = cppbor::Nint(-value).encode();
- }
- }
-
- string nameSpace;
- string name;
- vector<uint8_t> valueCbor;
- vector<int32_t> profileIds;
-};
-
-struct TestProfile {
- uint16_t id;
- vector<uint8_t> readerCertificate;
- bool userAuthenticationRequired;
- uint64_t timeoutMillis;
-};
-
-// ----------------------------------------------------------------
-
class IdentityAidl : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -108,39 +66,26 @@
TEST_P(IdentityAidl, createAndRetrieveCredential) {
// First, generate a key-pair for the reader since its public key will be
// part of the request data.
- optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
- ASSERT_TRUE(readerKeyPKCS8);
- optional<vector<uint8_t>> readerPublicKey =
- support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
- optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
- string serialDecimal = "1234";
- string issuer = "Android Open Source Project";
- string subject = "Android IdentityCredential VTS Test";
- time_t validityNotBefore = time(nullptr);
- time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
- optional<vector<uint8_t>> readerCertificate = support::ecPublicKeyGenerateCertificate(
- readerPublicKey.value(), readerKey.value(), serialDecimal, issuer, subject,
- validityNotBefore, validityNotAfter);
+ vector<uint8_t> readerKey;
+ optional<vector<uint8_t>> readerCertificate =
+ test_utils::GenerateReaderCertificate("1234", readerKey);
ASSERT_TRUE(readerCertificate);
// Make the portrait image really big (just shy of 256 KiB) to ensure that
// the chunking code gets exercised.
vector<uint8_t> portraitImage;
- portraitImage.resize(256 * 1024 - 10);
- for (size_t n = 0; n < portraitImage.size(); n++) {
- portraitImage[n] = (uint8_t)n;
- }
+ test_utils::SetImageData(portraitImage);
// Access control profiles:
- const vector<TestProfile> testProfiles = {// Profile 0 (reader authentication)
- {0, readerCertificate.value(), false, 0},
- // Profile 1 (no authentication)
- {1, {}, false, 0}};
+ const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
+ {0, readerCertificate.value(), false, 0},
+ // Profile 1 (no authentication)
+ {1, {}, false, 0}};
HardwareAuthToken authToken;
// Here's the actual test data:
- const vector<TestEntryData> testEntries = {
+ const vector<test_utils::TestEntryData> testEntries = {
{"PersonalData", "Last name", string("Turing"), vector<int32_t>{0, 1}},
{"PersonalData", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
{"PersonalData", "First name", string("Alan"), vector<int32_t>{0, 1}},
@@ -155,67 +100,33 @@
string cborPretty;
sp<IWritableIdentityCredential> writableCredential;
- string docType = "org.iso.18013-5.2019.mdl";
- bool testCredential = true;
- ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &writableCredential)
- .isOk());
- ASSERT_NE(writableCredential, nullptr);
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
string challenge = "attestationChallenge";
+ test_utils::AttestationData attData(writableCredential, challenge, {});
+ ASSERT_TRUE(attData.result.isOk())
+ << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
+ ASSERT_EQ(binder::Status::EX_NONE, attData.result.exceptionCode());
+ ASSERT_EQ(IIdentityCredentialStore::STATUS_OK, attData.result.serviceSpecificErrorCode());
+
// TODO: set it to something random and check it's in the cert chain
- vector<uint8_t> attestationApplicationId = {};
- vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
- vector<Certificate> attestationCertificates;
- ASSERT_TRUE(writableCredential
- ->getAttestationCertificate(attestationApplicationId, attestationChallenge,
- &attestationCertificates)
- .isOk());
- ASSERT_GE(attestationCertificates.size(), 2);
+ ASSERT_GE(attData.attestationCertificate.size(), 2);
ASSERT_TRUE(
writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts)
.isOk());
- vector<SecureAccessControlProfile> returnedSecureProfiles;
- for (const auto& testProfile : testProfiles) {
- SecureAccessControlProfile profile;
- Certificate cert;
- cert.encodedCertificate = testProfile.readerCertificate;
- ASSERT_TRUE(writableCredential
- ->addAccessControlProfile(testProfile.id, cert,
- testProfile.userAuthenticationRequired,
- testProfile.timeoutMillis,
- 0, // secureUserId
- &profile)
- .isOk());
- ASSERT_EQ(testProfile.id, profile.id);
- ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
- ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
- ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
- ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
- returnedSecureProfiles.push_back(profile);
- }
+ optional<vector<SecureAccessControlProfile>> secureProfiles =
+ test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+ ASSERT_TRUE(secureProfiles);
// Uses TestEntryData* pointer as key and values are the encrypted blobs. This
// is a little hacky but it works well enough.
- map<const TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
+ map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
for (const auto& entry : testEntries) {
- vector<vector<uint8_t>> chunks =
- support::chunkVector(entry.valueCbor, hwInfo.dataChunkSize);
-
- ASSERT_TRUE(writableCredential
- ->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
- entry.valueCbor.size())
- .isOk());
-
- vector<vector<uint8_t>> encryptedChunks;
- for (const auto& chunk : chunks) {
- vector<uint8_t> encryptedChunk;
- ASSERT_TRUE(writableCredential->addEntryValue(chunk, &encryptedChunk).isOk());
- encryptedChunks.push_back(encryptedChunk);
- }
- encryptedBlobs[&entry] = encryptedChunks;
+ ASSERT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+ encryptedBlobs, true));
}
vector<uint8_t> credentialData;
@@ -276,8 +187,8 @@
"]",
cborPretty);
- optional<vector<uint8_t>> credentialPubKey =
- support::certificateChainGetTopMostKey(attestationCertificates[0].encodedCertificate);
+ optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
+ attData.attestationCertificate[0].encodedCertificate);
ASSERT_TRUE(credentialPubKey);
EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
{}, // Additional data
@@ -347,8 +258,8 @@
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
optional<vector<uint8_t>> readerSignature =
- support::coseSignEcDsa(readerKey.value(), {}, // content
- dataToSign, // detached content
+ support::coseSignEcDsa(readerKey, {}, // content
+ dataToSign, // detached content
readerCertificate.value());
ASSERT_TRUE(readerSignature);
@@ -358,7 +269,7 @@
ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
ASSERT_TRUE(credential
- ->startRetrieval(returnedSecureProfiles, authToken, itemsRequestBytes,
+ ->startRetrieval(secureProfiles.value(), authToken, itemsRequestBytes,
signingKeyBlob, sessionTranscriptBytes,
readerSignature.value(), testEntriesEntryCounts)
.isOk());
@@ -405,6 +316,8 @@
cppbor::Array deviceAuthentication;
deviceAuthentication.add("DeviceAuthentication");
deviceAuthentication.add(sessionTranscript.clone());
+
+ string docType = "org.iso.18013-5.2019.mdl";
deviceAuthentication.add(docType);
deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
vector<uint8_t> encodedDeviceAuthentication = deviceAuthentication.encode();
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
new file mode 100644
index 0000000..b68fbb5
--- /dev/null
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -0,0 +1,683 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsIWritableIdentityCredentialTests"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+#include <gtest/gtest.h>
+#include <future>
+#include <map>
+
+#include "VtsIdentityTestUtils.h"
+
+namespace android::hardware::identity {
+
+using std::endl;
+using std::map;
+using std::optional;
+using std::string;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+class IdentityCredentialTests : public testing::TestWithParam<string> {
+ public:
+ virtual void SetUp() override {
+ credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
+ String16(GetParam().c_str()));
+ ASSERT_NE(credentialStore_, nullptr);
+ }
+
+ sp<IIdentityCredentialStore> credentialStore_;
+};
+
+TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ vector<uint8_t> attestationChallenge;
+ vector<Certificate> attestationCertificate;
+ vector<uint8_t> attestationApplicationId = {};
+ result = writableCredential->getAttestationCertificate(
+ attestationApplicationId, attestationChallenge, &attestationCertificate);
+
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ EXPECT_TRUE(test_utils::ValidateAttestationCertificate(attestationCertificate));
+}
+
+TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
+ vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
+ vector<Certificate> attestationCertificate;
+ vector<uint8_t> attestationApplicationId = {};
+
+ result = writableCredential->getAttestationCertificate(
+ attestationApplicationId, attestationChallenge, &attestationCertificate);
+
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ EXPECT_TRUE(test_utils::ValidateAttestationCertificate(attestationCertificate));
+}
+
+TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ string challenge = "NotSoRandomChallenge1";
+ test_utils::AttestationData attData(writableCredential, challenge, {});
+ ASSERT_TRUE(test_utils::ValidateAttestationCertificate(attData.attestationCertificate));
+
+ string challenge2 = "NotSoRandomChallenge2";
+ test_utils::AttestationData attData2(writableCredential, challenge2, {});
+ EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
+ << attData2.result.exceptionMessage() << endl;
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, attData2.result.serviceSpecificErrorCode());
+}
+
+TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ // First call should go through
+ const vector<int32_t> entryCounts = {2, 4};
+ result = writableCredential->startPersonalization(5, entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ // Call personalization again to check if repeat call is allowed.
+ result = writableCredential->startPersonalization(7, entryCounts);
+
+ // Second call to startPersonalization should have failed.
+ EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+}
+
+TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ // Verify minimal number of profile count and entry count
+ const vector<int32_t> entryCounts = {1, 1};
+ writableCredential->startPersonalization(1, entryCounts);
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+}
+
+TEST_P(IdentityCredentialTests, verifyStartPersonalizationZero) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ const vector<int32_t> entryCounts = {0};
+ writableCredential->startPersonalization(0, entryCounts);
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+}
+
+TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ // Verify minimal number of profile count and entry count
+ const vector<int32_t> entryCounts = {1};
+ writableCredential->startPersonalization(1, entryCounts);
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+}
+
+TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ // Verify set a large number of profile count and entry count is ok
+ const vector<int32_t> entryCounts = {3000};
+ writableCredential->startPersonalization(3500, entryCounts);
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+}
+
+TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ // Enter mismatched entry and profile numbers
+ const vector<int32_t> entryCounts = {5, 6};
+ writableCredential->startPersonalization(5, entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ optional<vector<uint8_t>> readerCertificate = test_utils::GenerateReaderCertificate("12345");
+ ASSERT_TRUE(readerCertificate);
+
+ const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
+ {1, readerCertificate.value(), false, 0},
+ {2, readerCertificate.value(), true, 1},
+ // Profile 4 (no authentication)
+ {4, {}, false, 0}};
+
+ optional<vector<SecureAccessControlProfile>> secureProfiles =
+ test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+ ASSERT_TRUE(secureProfiles);
+
+ vector<uint8_t> credentialData;
+ vector<uint8_t> proofOfProvisioningSignature;
+ result =
+ writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
+
+ // finishAddingEntries should fail because the number of addAccessControlProfile mismatched with
+ // startPersonalization, and begintest_utils::AddEntry was not called.
+ EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
+}
+
+TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
+ Status result;
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ const vector<int32_t> entryCounts = {3, 6};
+ writableCredential->startPersonalization(3, entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ const vector<test_utils::TestProfile> testProfiles = {// first profile should go though
+ {1, {}, true, 2},
+ // same id, different
+ // authentication requirement
+ {1, {}, true, 1},
+ // same id, different certificate
+ {1, {}, false, 0}};
+
+ bool expectOk = true;
+ for (const auto& testProfile : testProfiles) {
+ SecureAccessControlProfile profile;
+ Certificate cert;
+ cert.encodedCertificate = testProfile.readerCertificate;
+ result = writableCredential->addAccessControlProfile(
+ testProfile.id, cert, testProfile.userAuthenticationRequired,
+ testProfile.timeoutMillis, 0, &profile);
+
+ if (expectOk) {
+ expectOk = false;
+ // for profile should be allowed though as there are no duplications
+ // yet.
+ ASSERT_TRUE(result.isOk())
+ << result.exceptionCode() << "; " << result.exceptionMessage()
+ << "test profile id = " << testProfile.id << endl;
+
+ ASSERT_EQ(testProfile.id, profile.id);
+ ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
+ ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
+ ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
+ ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
+ } else {
+ // should not allow duplicate id profiles.
+ ASSERT_FALSE(result.isOk())
+ << result.exceptionCode() << "; " << result.exceptionMessage()
+ << ". Test profile id = " << testProfile.id
+ << ", timeout=" << testProfile.timeoutMillis << endl;
+ ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA,
+ result.serviceSpecificErrorCode());
+ }
+ }
+}
+
+TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
+ Status result;
+
+ HardwareInformation hwInfo;
+ ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ string challenge = "NotSoRandomChallenge1";
+ test_utils::AttestationData attData(writableCredential, challenge, {});
+ EXPECT_TRUE(attData.result.isOk())
+ << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
+
+ const vector<int32_t> entryCounts = {1u};
+ writableCredential->startPersonalization(1, entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+ ASSERT_TRUE(readerCertificate1);
+
+ const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
+
+ optional<vector<SecureAccessControlProfile>> secureProfiles =
+ test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+ ASSERT_TRUE(secureProfiles);
+
+ const vector<test_utils::TestEntryData> testEntries1 = {
+ {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
+ };
+
+ map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
+ for (const auto& entry : testEntries1) {
+ ASSERT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+ encryptedBlobs, true));
+ }
+
+ vector<uint8_t> credentialData;
+ vector<uint8_t> proofOfProvisioningSignature;
+ result =
+ writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
+
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ optional<vector<uint8_t>> proofOfProvisioning =
+ support::coseSignGetPayload(proofOfProvisioningSignature);
+ ASSERT_TRUE(proofOfProvisioning);
+ string cborPretty =
+ support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
+ EXPECT_EQ(
+ "[\n"
+ " 'ProofOfProvisioning',\n"
+ " 'org.iso.18013-5.2019.mdl',\n"
+ " [\n"
+ " {\n"
+ " 'id' : 1,\n"
+ " 'readerCertificate' : <not printed>,\n"
+ " 'userAuthenticationRequired' : true,\n"
+ " 'timeoutMillis' : 1,\n"
+ " },\n"
+ " ],\n"
+ " {\n"
+ " 'Name Space' : [\n"
+ " {\n"
+ " 'name' : 'Last name',\n"
+ " 'value' : 'Turing',\n"
+ " 'accessControlProfiles' : [0, 1, ],\n"
+ " },\n"
+ " ],\n"
+ " },\n"
+ " true,\n"
+ "]",
+ cborPretty);
+
+ optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
+ attData.attestationCertificate[0].encodedCertificate);
+ ASSERT_TRUE(credentialPubKey);
+ EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
+ {}, // Additional data
+ credentialPubKey.value()));
+}
+
+TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
+ Status result;
+
+ HardwareInformation hwInfo;
+ ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ string challenge = "NotSoRandomChallenge";
+ test_utils::AttestationData attData(writableCredential, challenge, {});
+ EXPECT_TRUE(attData.result.isOk())
+ << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
+
+ optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+ ASSERT_TRUE(readerCertificate1);
+
+ optional<vector<uint8_t>> readerCertificate2 = test_utils::GenerateReaderCertificate("1256");
+ ASSERT_TRUE(readerCertificate2);
+
+ const vector<test_utils::TestProfile> testProfiles = {
+ {1, readerCertificate1.value(), true, 1},
+ {2, readerCertificate2.value(), true, 2},
+ };
+ const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
+ writableCredential->startPersonalization(testProfiles.size(), entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ optional<vector<SecureAccessControlProfile>> secureProfiles =
+ test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+ ASSERT_TRUE(secureProfiles);
+
+ vector<uint8_t> portraitImage1;
+ test_utils::SetImageData(portraitImage1);
+
+ vector<uint8_t> portraitImage2;
+ test_utils::SetImageData(portraitImage2);
+
+ const vector<test_utils::TestEntryData> testEntries1 = {
+ {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
+ {"Name Space2", "Home address", string("Maida Vale, London, England"),
+ vector<int32_t>{1}},
+ {"Name Space2", "Work address", string("Maida Vale2, London, England"),
+ vector<int32_t>{2}},
+ {"Name Space2", "Trailer address", string("Maida, London, England"),
+ vector<int32_t>{1}},
+ {"Image", "Portrait image", portraitImage1, vector<int32_t>{1}},
+ {"Image2", "Work image", portraitImage2, vector<int32_t>{1, 2}},
+ {"Name Space3", "xyzw", string("random stuff"), vector<int32_t>{1, 2}},
+ {"Name Space3", "Something", string("Some string"), vector<int32_t>{2}},
+ };
+
+ map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
+ for (const auto& entry : testEntries1) {
+ EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+ encryptedBlobs, true));
+ }
+
+ vector<uint8_t> credentialData;
+ vector<uint8_t> proofOfProvisioningSignature;
+ result =
+ writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
+
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ optional<vector<uint8_t>> proofOfProvisioning =
+ support::coseSignGetPayload(proofOfProvisioningSignature);
+ ASSERT_TRUE(proofOfProvisioning);
+ string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(),
+ 32, //
+ {"readerCertificate"});
+ EXPECT_EQ(
+ "[\n"
+ " 'ProofOfProvisioning',\n"
+ " 'org.iso.18013-5.2019.mdl',\n"
+ " [\n"
+ " {\n"
+ " 'id' : 1,\n"
+ " 'readerCertificate' : <not printed>,\n"
+ " 'userAuthenticationRequired' : true,\n"
+ " 'timeoutMillis' : 1,\n"
+ " },\n"
+ " {\n"
+ " 'id' : 2,\n"
+ " 'readerCertificate' : <not printed>,\n"
+ " 'userAuthenticationRequired' : true,\n"
+ " 'timeoutMillis' : 2,\n"
+ " },\n"
+ " ],\n"
+ " {\n"
+ " 'Name Space 1' : [\n"
+ " {\n"
+ " 'name' : 'Last name',\n"
+ " 'value' : 'Turing',\n"
+ " 'accessControlProfiles' : [1, 2, ],\n"
+ " },\n"
+ " ],\n"
+ " 'Name Space2' : [\n"
+ " {\n"
+ " 'name' : 'Home address',\n"
+ " 'value' : 'Maida Vale, London, England',\n"
+ " 'accessControlProfiles' : [1, ],\n"
+ " },\n"
+ " {\n"
+ " 'name' : 'Work address',\n"
+ " 'value' : 'Maida Vale2, London, England',\n"
+ " 'accessControlProfiles' : [2, ],\n"
+ " },\n"
+ " {\n"
+ " 'name' : 'Trailer address',\n"
+ " 'value' : 'Maida, London, England',\n"
+ " 'accessControlProfiles' : [1, ],\n"
+ " },\n"
+ " ],\n"
+ " 'Image' : [\n"
+ " {\n"
+ " 'name' : 'Portrait image',\n"
+ " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
+ " 'accessControlProfiles' : [1, ],\n"
+ " },\n"
+ " ],\n"
+ " 'Image2' : [\n"
+ " {\n"
+ " 'name' : 'Work image',\n"
+ " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
+ " 'accessControlProfiles' : [1, 2, ],\n"
+ " },\n"
+ " ],\n"
+ " 'Name Space3' : [\n"
+ " {\n"
+ " 'name' : 'xyzw',\n"
+ " 'value' : 'random stuff',\n"
+ " 'accessControlProfiles' : [1, 2, ],\n"
+ " },\n"
+ " {\n"
+ " 'name' : 'Something',\n"
+ " 'value' : 'Some string',\n"
+ " 'accessControlProfiles' : [2, ],\n"
+ " },\n"
+ " ],\n"
+ " },\n"
+ " true,\n"
+ "]",
+ cborPretty);
+
+ optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
+ attData.attestationCertificate[0].encodedCertificate);
+ ASSERT_TRUE(credentialPubKey);
+ EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
+ {}, // Additional data
+ credentialPubKey.value()));
+}
+
+TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
+ Status result;
+
+ HardwareInformation hwInfo;
+ ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ string challenge = "NotSoRandomChallenge";
+ test_utils::AttestationData attData(writableCredential, challenge, {});
+ ASSERT_TRUE(attData.result.isOk())
+ << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
+
+ const vector<int32_t> entryCounts = {2u, 2u};
+ writableCredential->startPersonalization(3, entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+ ASSERT_TRUE(readerCertificate1);
+
+ optional<vector<uint8_t>> readerCertificate2 =
+ test_utils::GenerateReaderCertificate("123456987987987987987987");
+ ASSERT_TRUE(readerCertificate2);
+
+ const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
+ {1, readerCertificate2.value(), true, 1},
+ {2, {}, false, 0}};
+
+ optional<vector<SecureAccessControlProfile>> secureProfiles =
+ test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+ ASSERT_TRUE(secureProfiles);
+
+ const vector<test_utils::TestEntryData> testEntries1 = {
+ // test empty name space
+ {"", "t name", string("Turing"), vector<int32_t>{2}},
+ {"", "Birth", string("19120623"), vector<int32_t>{2}},
+ {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
+ {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
+ };
+
+ map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
+ for (const auto& entry : testEntries1) {
+ EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+ encryptedBlobs, true));
+ }
+
+ vector<uint8_t> credentialData;
+ vector<uint8_t> proofOfProvisioningSignature;
+ result =
+ writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
+
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+}
+
+TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
+ Status result;
+
+ HardwareInformation hwInfo;
+ ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ string challenge = "NotSoRandomChallenge";
+ test_utils::AttestationData attData(writableCredential, challenge, {});
+ ASSERT_TRUE(attData.result.isOk())
+ << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
+
+ // Enter mismatched entry and profile numbers.
+ // Technically the 2nd name space of "Name Space" occurs intermittently, 2
+ // before "Image" and 2 after image, which is not correct. All of same name
+ // space should occur together. Let's see if this fails.
+ const vector<int32_t> entryCounts = {2u, 1u, 2u};
+ writableCredential->startPersonalization(3, entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+ ASSERT_TRUE(readerCertificate1);
+
+ optional<vector<uint8_t>> readerCertificate2 =
+ test_utils::GenerateReaderCertificate("123456987987987987987987");
+ ASSERT_TRUE(readerCertificate2);
+
+ const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
+ {1, readerCertificate2.value(), true, 1},
+ {2, {}, false, 0}};
+
+ optional<vector<SecureAccessControlProfile>> secureProfiles =
+ test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+ ASSERT_TRUE(secureProfiles);
+
+ const vector<test_utils::TestEntryData> testEntries1 = {
+ // test empty name space
+ {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
+ {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
+ };
+
+ map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
+ for (const auto& entry : testEntries1) {
+ EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+ encryptedBlobs, true));
+ }
+ const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
+ vector<int32_t>{0, 1}};
+
+ EXPECT_TRUE(test_utils::AddEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
+ encryptedBlobs, true));
+
+ // We expect this to fail because the namespace is out of order, all "Name Space"
+ // should have been called together
+ const vector<test_utils::TestEntryData> testEntries3 = {
+ {"Name Space", "First name", string("Alan"), vector<int32_t>{0, 1}},
+ {"Name Space", "Home address", string("Maida Vale, London, England"),
+ vector<int32_t>{0}},
+ };
+
+ for (const auto& entry : testEntries3) {
+ EXPECT_FALSE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+ encryptedBlobs, false));
+ }
+
+ vector<uint8_t> credentialData;
+ vector<uint8_t> proofOfProvisioningSignature;
+ result =
+ writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
+
+ // should fail because test_utils::AddEntry should have failed earlier.
+ EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+ EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
+}
+
+TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
+ sp<IWritableIdentityCredential> writableCredential;
+ ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+
+ const vector<int32_t> entryCounts = {1};
+ Status result = writableCredential->startPersonalization(1, entryCounts);
+ ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << endl;
+
+ SecureAccessControlProfile profile;
+
+ // This should fail because the id is >= 32
+ result = writableCredential->addAccessControlProfile(32, // id
+ {}, // readerCertificate
+ false, // userAuthenticationRequired
+ 0, // timeoutMillis
+ 42, // secureUserId
+ &profile);
+ ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+ ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
+
+ // This should fail because the id is < 0
+ result = writableCredential->addAccessControlProfile(-1, // id
+ {}, // readerCertificate
+ false, // userAuthenticationRequired
+ 0, // timeoutMillis
+ 42, // secureUserId
+ &profile);
+ ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+ ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+ ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ Identity, IdentityCredentialTests,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
+ android::PrintInstanceNameToString);
+
+} // namespace android::hardware::identity
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
new file mode 100644
index 0000000..3aeebc6
--- /dev/null
+++ b/identity/aidl/vts/VtsIdentityTestUtils.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright 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.
+ */
+
+#include "VtsIdentityTestUtils.h"
+
+#include <aidl/Gtest.h>
+#include <map>
+
+namespace android::hardware::identity::test_utils {
+
+using std::endl;
+using std::map;
+using std::optional;
+using std::string;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+bool SetupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
+ sp<IIdentityCredentialStore>& credentialStore) {
+ if (credentialStore == nullptr) {
+ return false;
+ }
+
+ string docType = "org.iso.18013-5.2019.mdl";
+ bool testCredential = true;
+ Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
+
+ if (result.isOk() && writableCredential != nullptr) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal) {
+ vector<uint8_t> privKey;
+ return GenerateReaderCertificate(serialDecimal, privKey);
+}
+
+optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal,
+ vector<uint8_t>& readerPrivateKey) {
+ optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
+ if (!readerKeyPKCS8) {
+ return {};
+ }
+
+ optional<vector<uint8_t>> readerPublicKey =
+ support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
+ optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
+ if (!readerPublicKey || !readerKey) {
+ return {};
+ }
+
+ readerPrivateKey = readerKey.value();
+
+ string issuer = "Android Open Source Project";
+ string subject = "Android IdentityCredential VTS Test";
+ time_t validityNotBefore = time(nullptr);
+ time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
+
+ return support::ecPublicKeyGenerateCertificate(readerPublicKey.value(), readerKey.value(),
+ serialDecimal, issuer, subject,
+ validityNotBefore, validityNotAfter);
+}
+
+optional<vector<SecureAccessControlProfile>> AddAccessControlProfiles(
+ sp<IWritableIdentityCredential>& writableCredential,
+ const vector<TestProfile>& testProfiles) {
+ Status result;
+
+ vector<SecureAccessControlProfile> secureProfiles;
+
+ for (const auto& testProfile : testProfiles) {
+ SecureAccessControlProfile profile;
+ Certificate cert;
+ cert.encodedCertificate = testProfile.readerCertificate;
+ result = writableCredential->addAccessControlProfile(
+ testProfile.id, cert, testProfile.userAuthenticationRequired,
+ testProfile.timeoutMillis, 0, &profile);
+
+ // Don't use assert so all errors can be outputed. Then return
+ // instead of exit even on errors so caller can decide.
+ EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+ << "test profile id = " << testProfile.id << endl;
+ EXPECT_EQ(testProfile.id, profile.id);
+ EXPECT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
+ EXPECT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
+ EXPECT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
+ EXPECT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
+
+ if (!result.isOk() || testProfile.id != profile.id ||
+ testProfile.readerCertificate != profile.readerCertificate.encodedCertificate ||
+ testProfile.userAuthenticationRequired != profile.userAuthenticationRequired ||
+ testProfile.timeoutMillis != profile.timeoutMillis ||
+ support::kAesGcmTagSize + support::kAesGcmIvSize != profile.mac.size()) {
+ return {};
+ }
+
+ secureProfiles.push_back(profile);
+ }
+
+ return secureProfiles;
+}
+
+// Most test expects this function to pass. So we will print out additional
+// value if failed so more debug data can be provided.
+bool AddEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
+ int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
+ bool expectSuccess) {
+ Status result;
+ vector<vector<uint8_t>> chunks = support::chunkVector(entry.valueCbor, dataChunkSize);
+
+ result = writableCredential->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
+ entry.valueCbor.size());
+
+ if (expectSuccess) {
+ EXPECT_TRUE(result.isOk())
+ << result.exceptionCode() << "; " << result.exceptionMessage() << endl
+ << "entry name = " << entry.name << ", name space=" << entry.nameSpace << endl;
+ }
+
+ if (!result.isOk()) {
+ return false;
+ }
+
+ vector<vector<uint8_t>> encryptedChunks;
+ for (const auto& chunk : chunks) {
+ vector<uint8_t> encryptedContent;
+ result = writableCredential->addEntryValue(chunk, &encryptedContent);
+ if (expectSuccess) {
+ EXPECT_TRUE(result.isOk())
+ << result.exceptionCode() << "; " << result.exceptionMessage() << endl
+ << "entry name = " << entry.name << ", name space = " << entry.nameSpace
+ << endl;
+
+ EXPECT_GT(encryptedContent.size(), 0u) << "entry name = " << entry.name
+ << ", name space = " << entry.nameSpace << endl;
+ }
+
+ if (!result.isOk() || encryptedContent.size() <= 0u) {
+ return false;
+ }
+
+ encryptedChunks.push_back(encryptedContent);
+ }
+
+ encryptedBlobs[&entry] = encryptedChunks;
+ return true;
+}
+
+bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates) {
+ return (inputCertificates.size() >= 2);
+ // TODO: add parsing of the certificate and make sure it is genuine.
+}
+
+void SetImageData(vector<uint8_t>& image) {
+ image.resize(256 * 1024 - 10);
+ for (size_t n = 0; n < image.size(); n++) {
+ image[n] = (uint8_t)n;
+ }
+}
+
+} // namespace android::hardware::identity::test_utils
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.h b/identity/aidl/vts/VtsIdentityTestUtils.h
new file mode 100644
index 0000000..043ccd6
--- /dev/null
+++ b/identity/aidl/vts/VtsIdentityTestUtils.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VTS_IDENTITY_TEST_UTILS_H
+#define VTS_IDENTITY_TEST_UTILS_H
+
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+namespace android::hardware::identity::test_utils {
+
+using ::std::map;
+using ::std::optional;
+using ::std::string;
+using ::std::vector;
+
+using ::android::sp;
+using ::android::binder::Status;
+
+struct AttestationData {
+ AttestationData(sp<IWritableIdentityCredential>& writableCredential, string challenge,
+ vector<uint8_t> applicationId)
+ : attestationApplicationId(applicationId) {
+ // ASSERT_NE(writableCredential, nullptr);
+
+ if (!challenge.empty()) {
+ attestationChallenge.assign(challenge.begin(), challenge.end());
+ }
+
+ result = writableCredential->getAttestationCertificate(
+ attestationApplicationId, attestationChallenge, &attestationCertificate);
+ }
+
+ AttestationData() {}
+
+ vector<uint8_t> attestationChallenge;
+ vector<uint8_t> attestationApplicationId;
+ vector<Certificate> attestationCertificate;
+ Status result;
+};
+
+struct TestEntryData {
+ TestEntryData(string nameSpace, string name, vector<int32_t> profileIds)
+ : nameSpace(nameSpace), name(name), profileIds(profileIds) {}
+
+ TestEntryData(string nameSpace, string name, const string& value, vector<int32_t> profileIds)
+ : TestEntryData(nameSpace, name, profileIds) {
+ valueCbor = cppbor::Tstr(((const char*)value.data())).encode();
+ }
+ TestEntryData(string nameSpace, string name, const vector<uint8_t>& value,
+ vector<int32_t> profileIds)
+ : TestEntryData(nameSpace, name, profileIds) {
+ valueCbor = cppbor::Bstr(value).encode();
+ }
+ TestEntryData(string nameSpace, string name, bool value, vector<int32_t> profileIds)
+ : TestEntryData(nameSpace, name, profileIds) {
+ valueCbor = cppbor::Bool(value).encode();
+ }
+ TestEntryData(string nameSpace, string name, int64_t value, vector<int32_t> profileIds)
+ : TestEntryData(nameSpace, name, profileIds) {
+ if (value >= 0) {
+ valueCbor = cppbor::Uint(value).encode();
+ } else {
+ valueCbor = cppbor::Nint(-value).encode();
+ }
+ }
+
+ string nameSpace;
+ string name;
+ vector<uint8_t> valueCbor;
+ vector<int32_t> profileIds;
+};
+
+struct TestProfile {
+ uint16_t id;
+ vector<uint8_t> readerCertificate;
+ bool userAuthenticationRequired;
+ uint64_t timeoutMillis;
+};
+
+bool SetupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
+ sp<IIdentityCredentialStore>& credentialStore);
+
+optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal);
+
+optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal,
+ vector<uint8_t>& readerPrivateKey);
+
+optional<vector<SecureAccessControlProfile>> AddAccessControlProfiles(
+ sp<IWritableIdentityCredential>& writableCredential,
+ const vector<TestProfile>& testProfiles);
+
+bool AddEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
+ int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
+ bool expectSuccess);
+
+bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates);
+
+void SetImageData(vector<uint8_t>& image);
+
+} // namespace android::hardware::identity::test_utils
+
+#endif // VTS_IDENTITY_TEST_UTILS_H
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index bf6a5c3..dc49ddc 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -958,12 +958,17 @@
optional<vector<uint8_t>> createEcKeyPair() {
auto ec_key = EC_KEY_Ptr(EC_KEY_new());
auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
- auto group = 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 {};
}
+ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ if (group.get() == nullptr) {
+ LOG(ERROR) << "Error creating EC group by curve name";
+ 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";
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index 4db1398..4d6c9c3 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -24,6 +24,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/ir/1.0/vts/functional/Android.bp b/ir/1.0/vts/functional/Android.bp
index f9edebd..160129f 100644
--- a/ir/1.0/vts/functional/Android.bp
+++ b/ir/1.0/vts/functional/Android.bp
@@ -21,5 +21,5 @@
static_libs: [
"android.hardware.ir@1.0",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
index 36a6861..35b9387 100644
--- a/keymaster/3.0/vts/functional/Android.bp
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -29,5 +29,5 @@
"libcrypto_static",
"libsoftkeymasterdevice",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/keymaster/3.0/vts/functional/attestation_record.cpp b/keymaster/3.0/vts/functional/attestation_record.cpp
index a428989..bde4b57 100644
--- a/keymaster/3.0/vts/functional/attestation_record.cpp
+++ b/keymaster/3.0/vts/functional/attestation_record.cpp
@@ -46,7 +46,7 @@
typedef struct km_root_of_trust {
ASN1_OCTET_STRING* verified_boot_key;
- ASN1_BOOLEAN* device_locked;
+ ASN1_BOOLEAN device_locked;
ASN1_ENUMERATED* verified_boot_state;
} KM_ROOT_OF_TRUST;
diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp
index 27e00c1..bc294bd 100644
--- a/keymaster/4.0/support/attestation_record.cpp
+++ b/keymaster/4.0/support/attestation_record.cpp
@@ -50,7 +50,7 @@
typedef struct km_root_of_trust {
ASN1_OCTET_STRING* verified_boot_key;
- ASN1_BOOLEAN* device_locked;
+ ASN1_BOOLEAN device_locked;
ASN1_ENUMERATED* verified_boot_state;
ASN1_OCTET_STRING* verified_boot_hash;
} KM_ROOT_OF_TRUST;
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index db50080..e706c68 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -30,7 +30,7 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
index 9eab1db..63bf854 100644
--- a/keymaster/4.1/support/attestation_record.cpp
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -58,7 +58,7 @@
typedef struct km_root_of_trust {
ASN1_OCTET_STRING* verified_boot_key;
- ASN1_BOOLEAN* device_locked;
+ ASN1_BOOLEAN device_locked;
ASN1_ENUMERATED* verified_boot_state;
ASN1_OCTET_STRING* verified_boot_hash;
} KM_ROOT_OF_TRUST;
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
index 75d9139..f495796 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
@@ -31,17 +31,11 @@
// enumerate 4.1. devices.
using WrappedIKeymasterDevice = V4_0::IKeymasterDevice;
- Keymaster4(sp<V4_1::IKeymasterDevice> km4_1_dev, const hidl_string& instanceName)
- : Keymaster(V4_1::IKeymasterDevice::descriptor, instanceName),
- haveVersion_(false),
- km4_0_dev_(km4_1_dev),
- km4_1_dev_(km4_1_dev) {}
-
Keymaster4(sp<V4_0::IKeymasterDevice> km4_0_dev, const hidl_string& instanceName)
: Keymaster(V4_1::IKeymasterDevice::descriptor, instanceName),
haveVersion_(false),
km4_0_dev_(km4_0_dev),
- km4_1_dev_() {}
+ km4_1_dev_(V4_1::IKeymasterDevice::castFrom(km4_0_dev)) {}
const VersionResult& halVersion() const override {
const_cast<Keymaster4*>(this)->getVersionIfNeeded();
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
index c2d7fa3..5ba05ea 100644
--- a/keymaster/4.1/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -37,6 +37,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
index 6332c43..152c063 100644
--- a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
+++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
@@ -115,7 +115,9 @@
ErrorCode UseHmacKey(const HidlBuf& hmacKeyBlob) {
auto [result, mac, out_params] =
ProcessMessage(hmacKeyBlob, KeyPurpose::SIGN, "1234567890123456",
- AuthorizationSetBuilder().Authorization(TAG_MAC_LENGTH, 128));
+ AuthorizationSetBuilder()
+ .Authorization(TAG_MAC_LENGTH, 128)
+ .Digest(Digest::SHA_2_256));
return result;
}
diff --git a/keymaster/aidl/Android.bp b/keymaster/aidl/Android.bp
index a2d73ead..3011da6 100644
--- a/keymaster/aidl/Android.bp
+++ b/keymaster/aidl/Android.bp
@@ -15,4 +15,5 @@
},
},
},
+ versions: ["1"],
}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/1/.hash b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/.hash
new file mode 100644
index 0000000..4c441d4
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/.hash
@@ -0,0 +1 @@
+584fcb51e6025741fa62e16227c0158bf26a9195
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/HardwareAuthToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/HardwareAuthToken.aidl
new file mode 100644
index 0000000..db1df2b
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/HardwareAuthToken.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable HardwareAuthToken {
+ long challenge;
+ long userId;
+ long authenticatorId;
+ android.hardware.keymaster.HardwareAuthenticatorType authenticatorType;
+ android.hardware.keymaster.Timestamp timestamp;
+ byte[] mac;
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/HardwareAuthenticatorType.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/HardwareAuthenticatorType.aidl
new file mode 100644
index 0000000..924567f
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/HardwareAuthenticatorType.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@Backing(type="int") @VintfStability
+enum HardwareAuthenticatorType {
+ NONE = 0,
+ PASSWORD = 1,
+ FINGERPRINT = 2,
+ ANY = -1,
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/Timestamp.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/Timestamp.aidl
new file mode 100644
index 0000000..45fa1ae
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/1/android/hardware/keymaster/Timestamp.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable Timestamp {
+ long milliSeconds;
+}
diff --git a/light/2.0/vts/functional/Android.bp b/light/2.0/vts/functional/Android.bp
index 2c0a08f..06590c3 100644
--- a/light/2.0/vts/functional/Android.bp
+++ b/light/2.0/vts/functional/Android.bp
@@ -19,6 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalLightV2_0TargetTest.cpp"],
static_libs: ["android.hardware.light@2.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
index 916a857..91de3e9 100644
--- a/light/aidl/Android.bp
+++ b/light/aidl/Android.bp
@@ -15,4 +15,5 @@
},
},
},
+ versions: ["1"],
}
diff --git a/light/aidl/aidl_api/android.hardware.light/1/.hash b/light/aidl/aidl_api/android.hardware.light/1/.hash
new file mode 100644
index 0000000..e8fcb80
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/1/.hash
@@ -0,0 +1 @@
+33fec8401b6e66bddaeff251e1a2a0f4fa0d3bee
diff --git a/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/BrightnessMode.aidl b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/BrightnessMode.aidl
new file mode 100644
index 0000000..c4c6d64
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/BrightnessMode.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+enum BrightnessMode {
+ USER = 0,
+ SENSOR = 1,
+ LOW_PERSISTENCE = 2,
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/FlashMode.aidl b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/FlashMode.aidl
new file mode 100644
index 0000000..349f9f3
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/FlashMode.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+enum FlashMode {
+ NONE = 0,
+ TIMED = 1,
+ HARDWARE = 2,
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/HwLight.aidl b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/HwLight.aidl
new file mode 100644
index 0000000..c397f91
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/HwLight.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+parcelable HwLight {
+ int id;
+ int ordinal;
+ android.hardware.light.LightType type;
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/HwLightState.aidl b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/HwLightState.aidl
new file mode 100644
index 0000000..44a0882
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/HwLightState.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+parcelable HwLightState {
+ int color;
+ android.hardware.light.FlashMode flashMode;
+ int flashOnMs;
+ int flashOffMs;
+ android.hardware.light.BrightnessMode brightnessMode;
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/ILights.aidl b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/ILights.aidl
new file mode 100644
index 0000000..fc6c626
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/ILights.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+interface ILights {
+ void setLightState(in int id, in android.hardware.light.HwLightState state);
+ android.hardware.light.HwLight[] getLights();
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/LightType.aidl b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/LightType.aidl
new file mode 100644
index 0000000..77ab98c
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/LightType.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+enum LightType {
+ BACKLIGHT = 0,
+ KEYBOARD = 1,
+ BUTTONS = 2,
+ BATTERY = 3,
+ NOTIFICATIONS = 4,
+ ATTENTION = 5,
+ BLUETOOTH = 6,
+ WIFI = 7,
+ MICROPHONE = 8,
+}
diff --git a/light/aidl/vts/functional/Android.bp b/light/aidl/vts/functional/Android.bp
index 3dd8cf6..aa4719b 100644
--- a/light/aidl/vts/functional/Android.bp
+++ b/light/aidl/vts/functional/Android.bp
@@ -30,6 +30,6 @@
"android.hardware.light-cpp",
],
test_suites: [
- "vts-core",
+ "vts",
],
}
diff --git a/media/Android.bp b/media/Android.bp
new file mode 100644
index 0000000..267c02b
--- /dev/null
+++ b/media/Android.bp
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+
+filegroup {
+ name: "media_omx_audio_res",
+ path: "res",
+ srcs: ["res/*hz*"],
+}
+
+filegroup {
+ name: "media_omx_video_res",
+ path: "res",
+ srcs: ["res/*fps*"],
+}
diff --git a/media/omx/1.0/vts/functional/README.md b/media/omx/1.0/vts/functional/README.md
index 274b30d..c5a6867 100644
--- a/media/omx/1.0/vts/functional/README.md
+++ b/media/omx/1.0/vts/functional/README.md
@@ -6,29 +6,27 @@
#### master :
Functionality of master is to enumerate all the omx components (and the roles it supports) available in android media framework.
-usage: VtsHalMediaOmxV1\_0TargetMasterTest -I default
+usage: atest VtsHalMediaOmxV1\_0TargetMasterTest
#### component :
This folder includes test fixtures that tests aspects common to all omx compatible components. For instance, port enabling/disabling, enumerating port formats, state transitions, flush, ..., stay common to all components irrespective of the service they offer. Test fixtures here are directed towards testing these (omx core). Every standard OMX compatible component is expected to pass these tests.
-usage: VtsHalMediaOmxV1\_0TargetComponentTest -I default -C <comp name> -R <comp role>
+usage: atest VtsHalMediaOmxV1\_0TargetComponentTest
#### audio :
This folder includes test fixtures associated with testing audio encoder and decoder components such as simple encoding of a raw clip or decoding of an elementary stream, end of stream test, timestamp deviations test, flush test and so on. These tests are aimed towards testing the plugin that connects the component to the omx core.
usage:
-VtsHalMediaOmxV1\_0TargetAudioDecTest -I default -C <comp name> -R audio_decoder.<comp class> -P /data/local/tmp/media/
+atest VtsHalMediaOmxV1\_0TargetAudioDecTest
-VtsHalMediaOmxV1\_0TargetAudioEncTest -I default -C <comp name> -R audio_encoder.<comp class> -P /data/local/tmp/media/
+atest VtsHalMediaOmxV1\_0TargetAudioEncTest
#### video :
This folder includes test fixtures associated with testing video encoder and decoder components such as simple encoding of a raw clip or decoding of an elementary stream, end of stream test, timestamp deviations test, flush test and so on. These tests are aimed towards testing the plugin that connects the component to the omx core.
usage:
-VtsHalMediaOmxV1\_0TargetVideoDecTest -I default -C <comp name> -R video_decoder.<comp class> -P /data/local/tmp/media/
+atest VtsHalMediaOmxV1\_0TargetVideoDecTest
-VtsHalMediaOmxV1\_0TargetVideoEncTest -I default -C <comp name> -R video_encoder.<comp class> -P /data/local/tmp/media/
-
-While tesing audio/video encoder, decoder components, test fixtures require input files. These input are files are present in the folder 'res'. Before running the tests all the files in 'res' have to be placed in '/data/local/tmp/media' or a path of your choice and this path needs to be provided as an argument to the test application
+atest VtsHalMediaOmxV1\_0TargetVideoEncTest
diff --git a/media/omx/1.0/vts/functional/audio/Android.bp b/media/omx/1.0/vts/functional/audio/Android.bp
index 7418bb4..ec7357c 100644
--- a/media/omx/1.0/vts/functional/audio/Android.bp
+++ b/media/omx/1.0/vts/functional/audio/Android.bp
@@ -16,22 +16,30 @@
cc_test {
name: "VtsHalMediaOmxV1_0TargetAudioEncTest",
+ stem: "vts_hal_media_omx_v1_0_audio_enc_test",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
srcs: [
"VtsHalMediaOmxV1_0TargetAudioEncTest.cpp",
- "media_audio_hidl_test_common.cpp"
+ "media_audio_hidl_test_common.cpp",
],
- test_suites: ["general-tests"],
+ data: [":media_omx_audio_res"],
+ test_config: "VtsHalMediaOmxV1_0TargetAudioEncTest.xml",
+ test_suites: [
+ "vts",
+ ],
}
cc_test {
name: "VtsHalMediaOmxV1_0TargetAudioDecTest",
+ stem: "vts_hal_media_omx_v1_0_audio_dec_test",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
srcs: [
"VtsHalMediaOmxV1_0TargetAudioDecTest.cpp",
- "media_audio_hidl_test_common.cpp"
+ "media_audio_hidl_test_common.cpp",
],
- test_suites: ["general-tests"],
+ data: [":media_omx_audio_res"],
+ test_config: "VtsHalMediaOmxV1_0TargetAudioDecTest.xml",
+ test_suites: [
+ "vts",
+ ],
}
-
-
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
index 4543c01..3ed5670 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
@@ -28,6 +28,8 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
@@ -44,48 +46,45 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_audio_hidl_test_common.h>
-#include <media_hidl_test_common.h>
#include <fstream>
-static ComponentTestEnvironment* gEnv = nullptr;
+// Resource directory
+std::string sResourceDir = "";
// audio decoder test fixture class
-class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Role: " + gEnv->getRole().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
+class AudioDecHidlTest
+ : public ::testing::TestWithParam<std::tuple<std::string, std::string, std::string>> {
+ public:
+ ::std::string getTestCaseInfo() const {
+ return ::std::string() + "Component: " + component_ + " | " + "Role: " + role_ + " | " +
+ "Instance: " + instance_ + " | " + "Res: " + sResourceDir;
}
virtual void SetUp() override {
- Super::SetUp();
+ instance_ = std::get<0>(GetParam());
+ component_ = std::get<1>(GetParam());
+ role_ = std::get<2>(GetParam());
+ ASSERT_NE(sResourceDir.empty(), true);
+
disableTest = false;
android::hardware::media::omx::V1_0::Status status;
- omx = Super::getService<IOmx>(gEnv->getInstance());
+ omx = IOmx::getService(instance_);
ASSERT_NE(omx, nullptr);
observer =
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
handleMessage(msg, buffer);
});
ASSERT_NE(observer, nullptr);
- if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
- disableTest = true;
- EXPECT_TRUE(omx->allocateNode(
- gEnv->getComponent(), observer,
- [&](android::hardware::media::omx::V1_0::Status _s,
- sp<IOmxNode> const& _nl) {
- status = _s;
- this->omxNode = _nl;
- })
- .isOk());
+ if (component_.find("OMX.") != 0) disableTest = true;
+ EXPECT_TRUE(omx->allocateNode(component_, observer,
+ [&](android::hardware::media::omx::V1_0::Status _s,
+ sp<IOmxNode> const& _nl) {
+ status = _s;
+ this->omxNode = _nl;
+ })
+ .isOk());
if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
disableTest = true;
std::cout << "[ WARN ] Test Disabled, component not present\n";
@@ -93,7 +92,7 @@
}
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
ASSERT_NE(omxNode, nullptr);
- ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
+ ASSERT_NE(role_.empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
@@ -108,7 +107,7 @@
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
- strcpy(substring, gEnv->getRole().c_str());
+ strcpy(substring, role_.c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
@@ -153,11 +152,8 @@
timestampDevTest = false;
isSecure = false;
size_t suffixLen = strlen(".secure");
- if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
- isSecure =
- !strcmp(gEnv->getComponent().c_str() +
- strlen(gEnv->getComponent().c_str()) - suffixLen,
- ".secure");
+ if (component_.rfind(".secure") == component_.length() - suffixLen) {
+ isSecure = true;
}
if (isSecure) disableTest = true;
if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
@@ -172,7 +168,6 @@
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
- Super::TearDown();
}
// callback function to process messages received by onMessages() from IL
@@ -249,6 +244,10 @@
unknown_comp,
};
+ std::string component_;
+ std::string role_;
+ std::string instance_;
+
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
@@ -656,21 +655,21 @@
}
// set component role
-TEST_F(AudioDecHidlTest, SetRole) {
+TEST_P(AudioDecHidlTest, SetRole) {
description("Test Set Component Role");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// port format enumeration
-TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
+TEST_P(AudioDecHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -687,12 +686,12 @@
// test port settings reconfiguration, elementary stream decode and timestamp
// deviation
-TEST_F(AudioDecHidlTest, DecodeTest) {
+TEST_P(AudioDecHidlTest, DecodeTest) {
description("Tests Port Reconfiguration, Decode and timestamp deviation");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -702,8 +701,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -776,12 +775,12 @@
}
// end of sequence test
-TEST_F(AudioDecHidlTest, EOSTest_M) {
+TEST_P(AudioDecHidlTest, EOSTest_M) {
description("Test end of stream monkeying");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -840,12 +839,12 @@
}
// end of sequence test
-TEST_F(AudioDecHidlTest, ThumbnailTest) {
+TEST_P(AudioDecHidlTest, ThumbnailTest) {
description("Test Request for thumbnail");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -855,8 +854,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -954,12 +953,12 @@
}
// end of sequence test
-TEST_F(AudioDecHidlTest, SimpleEOSTest) {
+TEST_P(AudioDecHidlTest, SimpleEOSTest) {
description("Test end of stream");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -969,8 +968,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -1046,12 +1045,12 @@
}
// test input/output port flush
-TEST_F(AudioDecHidlTest, FlushTest) {
+TEST_P(AudioDecHidlTest, FlushTest) {
description("Test Flush");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -1061,8 +1060,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -1153,15 +1152,21 @@
kPortIndexOutput));
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, AudioDecHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
+ kTestParameters = getTestParameters("audio_decoder");
::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
}
- return status;
-}
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.xml b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.xml
new file mode 100644
index 0000000..275fefe
--- /dev/null
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalMediaOmxV1_0TargetAudioDecTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_hal_media_omx_v1_0_audio_dec_test" value="/data/local/tmp/vts_hal_media_omx_v1_0_audio_dec_test" />
+
+ <!-- Files used for audio testing -->
+ <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.aac" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.aac" />
+ <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.amrwb" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.amrwb" />
+ <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.info" />
+ <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.flac" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.flac" />
+ <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.info" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.info" />
+ <option name="push-file" key="bbb_g711alaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.info" />
+ <option name="push-file" key="bbb_g711alaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.raw" />
+ <option name="push-file" key="bbb_g711mulaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.info" />
+ <option name="push-file" key="bbb_g711mulaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.raw" />
+ <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.info" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.info" />
+ <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.raw" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.raw" />
+ <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.info" />
+ <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.mp3" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.mp3" />
+ <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
+ <option name="push-file" key="bbb_raw_1ch_16khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_16khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s32le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.raw" />
+ <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+ <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
+ <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.amrnb" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.amrnb" />
+ <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.info" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_hal_media_omx_v1_0_audio_dec_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
index 0ebab88..32e6f4c 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
@@ -28,6 +28,8 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
@@ -44,48 +46,45 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_audio_hidl_test_common.h>
-#include <media_hidl_test_common.h>
#include <fstream>
-static ComponentTestEnvironment* gEnv = nullptr;
+// Resource directory
+std::string sResourceDir = "";
// audio encoder test fixture class
-class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Role: " + gEnv->getRole().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
+class AudioEncHidlTest
+ : public ::testing::TestWithParam<std::tuple<std::string, std::string, std::string>> {
+ public:
+ ::std::string getTestCaseInfo() const {
+ return ::std::string() + "Component: " + component_ + " | " + "Role: " + role_ + " | " +
+ "Instance: " + instance_ + " | " + "Res: " + sResourceDir;
}
virtual void SetUp() override {
- Super::SetUp();
+ instance_ = std::get<0>(GetParam());
+ component_ = std::get<1>(GetParam());
+ role_ = std::get<2>(GetParam());
+ ASSERT_NE(sResourceDir.empty(), true);
+
disableTest = false;
android::hardware::media::omx::V1_0::Status status;
- omx = Super::getService<IOmx>(gEnv->getInstance());
+ omx = IOmx::getService(instance_);
ASSERT_NE(omx, nullptr);
observer =
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
handleMessage(msg, buffer);
});
ASSERT_NE(observer, nullptr);
- if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
- disableTest = true;
- EXPECT_TRUE(omx->allocateNode(
- gEnv->getComponent(), observer,
- [&](android::hardware::media::omx::V1_0::Status _s,
- sp<IOmxNode> const& _nl) {
- status = _s;
- this->omxNode = _nl;
- })
- .isOk());
+ if (component_.find("OMX.") != 0) disableTest = true;
+ EXPECT_TRUE(omx->allocateNode(component_, observer,
+ [&](android::hardware::media::omx::V1_0::Status _s,
+ sp<IOmxNode> const& _nl) {
+ status = _s;
+ this->omxNode = _nl;
+ })
+ .isOk());
if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
disableTest = true;
std::cout << "[ WARN ] Test Disabled, component not present\n";
@@ -93,7 +92,7 @@
}
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
ASSERT_NE(omxNode, nullptr);
- ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
+ ASSERT_NE(role_.empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
@@ -105,7 +104,7 @@
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
- strcpy(substring, gEnv->getRole().c_str());
+ strcpy(substring, role_.c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
@@ -149,7 +148,6 @@
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
- Super::TearDown();
}
// callback function to process messages received by onMessages() from IL
@@ -190,6 +188,10 @@
unknown_comp,
};
+ std::string component_;
+ std::string role_;
+ std::string instance_;
+
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
@@ -364,21 +366,21 @@
}
// set component role
-TEST_F(AudioEncHidlTest, SetRole) {
+TEST_P(AudioEncHidlTest, SetRole) {
description("Test Set Component Role");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_.c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// port format enumeration
-TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
+TEST_P(AudioEncHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -394,12 +396,12 @@
}
// test raw stream encode
-TEST_F(AudioEncHidlTest, SimpleEncodeTest) {
+TEST_P(AudioEncHidlTest, SimpleEncodeTest) {
description("Tests Basic encoding and EOS");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
@@ -409,7 +411,7 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512];
- strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
GetURLForComponent(compName, mURL);
std::ifstream eleStream;
@@ -484,15 +486,21 @@
kPortIndexOutput));
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, AudioEncHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
+ kTestParameters = getTestParameters("audio_encoder");
::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
}
- return status;
-}
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.xml b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.xml
new file mode 100644
index 0000000..88b6c87
--- /dev/null
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalMediaOmxV1_0TargetAudioEncTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_hal_media_omx_v1_0_audio_enc_test" value="/data/local/tmp/vts_hal_media_omx_v1_0_audio_enc_test" />
+
+ <!-- Files used for audio testing -->
+ <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.aac" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.aac" />
+ <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.amrwb" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.amrwb" />
+ <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.info" />
+ <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.flac" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.flac" />
+ <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.info" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.info" />
+ <option name="push-file" key="bbb_g711alaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.info" />
+ <option name="push-file" key="bbb_g711alaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.raw" />
+ <option name="push-file" key="bbb_g711mulaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.info" />
+ <option name="push-file" key="bbb_g711mulaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.raw" />
+ <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.info" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.info" />
+ <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.raw" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.raw" />
+ <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.info" />
+ <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.mp3" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.mp3" />
+ <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
+ <option name="push-file" key="bbb_raw_1ch_16khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_16khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s32le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.raw" />
+ <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+ <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
+ <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.amrnb" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.amrnb" />
+ <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.info" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_hal_media_omx_v1_0_audio_enc_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
index e7ae083..7c3b23f 100644
--- a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
@@ -44,7 +44,6 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <hidlmemory/mapping.h>
#include <media_audio_hidl_test_common.h>
#include <media_hidl_test_common.h>
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 5a79e55..2c024a0 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -23,7 +23,7 @@
export_include_dirs: ["."],
static_libs: [
- "VtsHalHidlTargetTestBase",
+ "libgtest",
"libhidlmemory",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 8d4c022..d9d1157 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -56,17 +56,16 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <hidlmemory/mapping.h>
#include <media/hardware/HardwareAPI.h>
#include <media_hidl_test_common.h>
#include <memory>
// set component role
-Return<android::hardware::media::omx::V1_0::Status> setRole(
- sp<IOmxNode> omxNode, const char* role) {
+Return<android::hardware::media::omx::V1_0::Status> setRole(sp<IOmxNode> omxNode,
+ const std::string& role) {
OMX_PARAM_COMPONENTROLETYPE params;
- strcpy((char*)params.cRole, role);
+ strcpy((char*)params.cRole, role.c_str());
return setParam(omxNode, OMX_IndexParamStandardComponentRole, ¶ms);
}
@@ -759,3 +758,46 @@
EXPECT_EQ(eosFlag, true);
eosFlag = false;
}
+
+hidl_vec<IOmx::ComponentInfo> getComponentInfoList(sp<IOmx> omx) {
+ android::hardware::media::omx::V1_0::Status status;
+ hidl_vec<IOmx::ComponentInfo> nodeList;
+ omx->listNodes([&status, &nodeList](android::hardware::media::omx::V1_0::Status _s,
+ hidl_vec<IOmx::ComponentInfo> const& _nl) {
+ status = _s;
+ nodeList = _nl;
+ });
+ if (status != android::hardware::media::omx::V1_0::Status::OK) {
+ ALOGE("Failed to get ComponentInfo list for IOmx.");
+ }
+ return nodeList;
+}
+
+// Return all test parameters, a list of tuple of <instance, component, role>
+const std::vector<std::tuple<std::string, std::string, std::string>>& getTestParameters(
+ const std::string& filter) {
+ static std::vector<std::tuple<std::string, std::string, std::string>> parameters;
+
+ auto instances = android::hardware::getAllHalInstanceNames(IOmx::descriptor);
+ for (std::string instance : instances) {
+ sp<IOmx> omx = IOmx::getService(instance);
+ hidl_vec<IOmx::ComponentInfo> componentInfos = getComponentInfoList(omx);
+ for (IOmx::ComponentInfo info : componentInfos) {
+ for (std::string role : info.mRoles) {
+ if (filter.empty()) {
+ if (kWhiteListRoles.find(role.c_str()) == kWhiteListRoles.end()) {
+ // This is for component test and the role is not in the white list.
+ continue;
+ }
+ } else if (role.find(filter) == std::string::npos) {
+ // The role doesn't match the given filter, e.g., video_decoder_vp8 role doesn't
+ // need to run for audio_decoder tests.
+ continue;
+ }
+ parameters.push_back(std::make_tuple(instance, info.mName.c_str(), role.c_str()));
+ }
+ }
+ }
+
+ return parameters;
+}
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index ac077a3..bb03dd0 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -32,6 +32,8 @@
#include <android/hardware/graphics/mapper/2.0/types.h>
#include <android/hardware/graphics/mapper/3.0/IMapper.h>
#include <android/hardware/graphics/mapper/3.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/ServiceManagement.h>
#include <media/stagefright/foundation/ALooper.h>
#include <utils/Condition.h>
#include <utils/List.h>
@@ -44,8 +46,6 @@
#include <media/openmax/OMX_AudioExt.h>
#include <media/openmax/OMX_VideoExt.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-
/* TIME OUTS (Wait time in dequeueMessage()) */
/* As component is switching states (loaded<->idle<->execute), dequeueMessage()
@@ -78,6 +78,20 @@
unknown,
};
+// White list audio/video roles to be tested.
+static std::set<std::string> kWhiteListRoles{
+ "audio_encoder.aac", "audio_encoder.amrnb", "audio_encoder.amrwb",
+ "audio_encoder.flac", "audio_decoder.aac", "audio_decoder.amrnb",
+ "audio_decoder.amrwb", "audio_decoder.flac", "audio_decoder.g711alaw",
+ "audio_decoder.g711mlaw", "audio_decoder.gsm", "audio_decoder.mp3",
+ "audio_decoder.opus", "audio_decoder.raw", "audio_decoder.vorbis",
+ "video_encoder.avc", "video_encoder.h263", "video_encoder.mpeg4",
+ "video_encoder.vp8", "video_encoder.vp9", "video_decoder.avc",
+ "video_decoder.h263", "video_decoder.hevc", "video_decoder.mpeg4",
+ "video_decoder.vp8", "video_decoder.vp9"};
+
+static std::vector<std::tuple<std::string, std::string, std::string>> kTestParameters;
+
/*
* TODO: below definitions are borrowed from Conversion.h.
* This is not the ideal way to do it. Loose these definitions once you
@@ -328,8 +342,8 @@
using Rect = IMapper::Rect;
};
-Return<android::hardware::media::omx::V1_0::Status> setRole(
- sp<IOmxNode> omxNode, const char* role);
+Return<android::hardware::media::omx::V1_0::Status> setRole(sp<IOmxNode> omxNode,
+ const std::string& role);
Return<android::hardware::media::omx::V1_0::Status> setPortBufferSize(
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 size);
@@ -400,77 +414,10 @@
portreconfig fptr = nullptr, OMX_U32 kPortIndexInput = 0,
OMX_U32 kPortIndexOutput = 1, void* args = nullptr);
-// A class for test environment setup
-class ComponentTestEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestEnvBase Super;
+hidl_vec<IOmx::ComponentInfo> getComponentInfoList(sp<IOmx> omx);
- public:
- virtual void registerTestServices() override { registerTestService<IOmx>(); }
-
- ComponentTestEnvironment() : res("/data/local/tmp/media/") {}
-
- void setComponent(const char* _component) { component = _component; }
-
- void setRole(const char* _role) { role = _role; }
-
- void setRes(const char* _res) { res = _res; }
-
- const hidl_string getInstance() { return Super::getServiceName<IOmx>(); }
-
- const hidl_string getComponent() const { return component; }
-
- const hidl_string getRole() const { return role; }
-
- const hidl_string getRes() const { return res; }
-
- int initFromOptions(int argc, char** argv) {
- static struct option options[] = {{"component", required_argument, 0, 'C'},
- {"role", required_argument, 0, 'R'},
- {"res", required_argument, 0, 'P'},
- {0, 0, 0, 0}};
-
- while (true) {
- int index = 0;
- int c = getopt_long(argc, argv, "C:R:P:", options, &index);
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 'C':
- setComponent(optarg);
- break;
- case 'R':
- setRole(optarg);
- break;
- case 'P':
- setRes(optarg);
- break;
- case '?':
- break;
- }
- }
-
- if (optind < argc) {
- fprintf(stderr,
- "unrecognized option: %s\n\n"
- "usage: %s <gtest options> <test options>\n\n"
- "test options are:\n\n"
- "-C, --component: OMX component to test\n"
- "-R, --role: OMX component Role\n"
- "-P, --res: Resource files directory location\n",
- argv[optind ?: 1], argv[0]);
- return 2;
- }
- return 0;
- }
-
- private:
- hidl_string instance;
- hidl_string component;
- hidl_string role;
- hidl_string res;
-};
+// Return all test parameters, a list of tuple of <instance, component, role>
+const std::vector<std::tuple<std::string, std::string, std::string>>& getTestParameters(
+ const std::string& filter);
#endif // MEDIA_HIDL_TEST_COMMON_H
diff --git a/media/omx/1.0/vts/functional/component/Android.bp b/media/omx/1.0/vts/functional/component/Android.bp
index 970eabe..8fb627a 100644
--- a/media/omx/1.0/vts/functional/component/Android.bp
+++ b/media/omx/1.0/vts/functional/component/Android.bp
@@ -18,6 +18,7 @@
name: "VtsHalMediaOmxV1_0TargetComponentTest",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
- test_suites: ["general-tests"],
+ test_suites: [
+ "vts",
+ ],
}
-
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 1c1d39b..01cec6d 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -28,6 +28,8 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
@@ -44,42 +46,37 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_hidl_test_common.h>
-static ComponentTestEnvironment* gEnv = nullptr;
-
// generic component test fixture class
-class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Role: " + gEnv->getRole().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str();
+class ComponentHidlTest
+ : public ::testing::TestWithParam<std::tuple<std::string, std::string, std::string>> {
+ public:
+ ::std::string getTestCaseInfo() const {
+ return ::std::string() + "Component: " + component_ + " | " + "Role: " + role_ + " | " +
+ "Instance: " + instance_;
}
virtual void SetUp() override {
- Super::SetUp();
+ instance_ = std::get<0>(GetParam());
+ component_ = std::get<1>(GetParam());
+ role_ = std::get<2>(GetParam());
+
disableTest = false;
android::hardware::media::omx::V1_0::Status status;
- omx = Super::getService<IOmx>(gEnv->getInstance());
+ omx = IOmx::getService(instance_);
ASSERT_NE(omx, nullptr);
observer = new CodecObserver(nullptr);
ASSERT_NE(observer, nullptr);
- if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
- disableTest = true;
- EXPECT_TRUE(omx->allocateNode(
- gEnv->getComponent(), observer,
- [&](android::hardware::media::omx::V1_0::Status _s,
- sp<IOmxNode> const& _nl) {
- status = _s;
- this->omxNode = _nl;
- })
- .isOk());
+ if (component_.find("OMX.") != 0) disableTest = true;
+ EXPECT_TRUE(omx->allocateNode(component_, observer,
+ [&](android::hardware::media::omx::V1_0::Status _s,
+ sp<IOmxNode> const& _nl) {
+ status = _s;
+ this->omxNode = _nl;
+ })
+ .isOk());
if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
disableTest = true;
std::cout << "[ WARN ] Test Disabled, component not present\n";
@@ -87,7 +84,7 @@
}
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_NE(omxNode, nullptr);
- ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
+ ASSERT_NE(role_.empty(), true) << "Invalid Component Role";
struct StringToClass {
const char* Class;
standardCompClass CompClass;
@@ -102,7 +99,7 @@
sizeof(kStringToClass) / sizeof(kStringToClass[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
- strcpy(substring, gEnv->getRole().c_str());
+ strcpy(substring, role_.c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr) << "Invalid Component Role";
substring[pch - substring] = '\0';
@@ -117,11 +114,8 @@
isSecure = false;
mTunnel = false;
size_t suffixLen = strlen(".secure");
- if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
- isSecure =
- !strcmp(gEnv->getComponent().c_str() +
- strlen(gEnv->getComponent().c_str()) - suffixLen,
- ".secure");
+ if (component_.rfind(".secure") == component_.length() - suffixLen) {
+ isSecure = true;
}
if (compClass == video_decoder) {
omxNode->configureVideoTunnelMode(
@@ -147,7 +141,6 @@
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
- Super::TearDown();
}
enum standardCompClass {
@@ -158,6 +151,10 @@
unknown_class,
};
+ std::string component_;
+ std::string role_;
+ std::string instance_;
+
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
@@ -191,7 +188,7 @@
}
// test dispatch message API call
-TEST_F(ComponentHidlTest, dispatchMsg) {
+TEST_P(ComponentHidlTest, dispatchMsg) {
description("test dispatch message API call");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
@@ -216,22 +213,22 @@
}
// set component role
-TEST_F(ComponentHidlTest, SetRole) {
+TEST_P(ComponentHidlTest, SetRole) {
description("Test Set Component Role");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// port indices enumeration
-TEST_F(ComponentHidlTest, DISABLED_GetPortIndices) {
+TEST_P(ComponentHidlTest, DISABLED_GetPortIndices) {
description("Test Component on Mandatory Port Parameters (Port Indices)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
OMX_PORT_PARAM_TYPE params;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
// Get Number of Ports and their Indices for all Domains
@@ -248,13 +245,13 @@
}
// port format enumeration
-TEST_F(ComponentHidlTest, EnumeratePortFormat) {
+TEST_P(ComponentHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -308,14 +305,14 @@
}
// get/set default port settings of a component
-TEST_F(ComponentHidlTest, DISABLED_SetDefaultPortParams) {
+TEST_P(ComponentHidlTest, DISABLED_SetDefaultPortParams) {
description(
"Test Component on Mandatory Port Parameters (Port Definition)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -398,7 +395,7 @@
portDef = mirror;
OMX_U32 nBufferSize = portDef.nBufferSize >> 1;
if (nBufferSize != 0) {
- if (!strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11)) {
+ if (component_.find("OMX.google.") != 0) {
portDef.nBufferSize = nBufferSize;
} else {
// Probable alignment requirements of vendor component
@@ -438,13 +435,13 @@
}
// populate port test
-TEST_F(ComponentHidlTest, DISABLED_PopulatePort) {
+TEST_P(ComponentHidlTest, DISABLED_PopulatePort) {
description("Verify bPopulated field of a component port");
if (disableTest || isSecure) return;
android::hardware::media::omx::V1_0::Status status;
OMX_U32 portBase = 0;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -490,14 +487,14 @@
}
// Flush test
-TEST_F(ComponentHidlTest, Flush) {
+TEST_P(ComponentHidlTest, Flush) {
description("Test Flush");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -561,14 +558,14 @@
}
// Flush test - monkeying
-TEST_F(ComponentHidlTest, Flush_M) {
+TEST_P(ComponentHidlTest, Flush_M) {
description("Test Flush monkeying");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -669,14 +666,14 @@
}
// test port mode configuration when the component is in various states
-TEST_F(ComponentHidlTest, PortModeConfig) {
+TEST_P(ComponentHidlTest, PortModeConfig) {
description("Test Port Mode Configuration");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -733,14 +730,14 @@
}
// state transitions test
-TEST_F(ComponentHidlTest, StateTransitions) {
+TEST_P(ComponentHidlTest, StateTransitions) {
description("Test State Transitions Loaded<->Idle<->Execute");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_U32 portBase = 0;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -852,14 +849,14 @@
}
// state transitions test - monkeying
-TEST_F(ComponentHidlTest, DISABLED_StateTransitions_M) {
+TEST_P(ComponentHidlTest, DISABLED_StateTransitions_M) {
description("Test State Transitions monkeying");
if (disableTest || isSecure) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -918,13 +915,13 @@
}
// port enable disable test
-TEST_F(ComponentHidlTest, DISABLED_PortEnableDisable_Loaded) {
+TEST_P(ComponentHidlTest, DISABLED_PortEnableDisable_Loaded) {
description("Test Port Enable and Disable (Component State :: Loaded)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
OMX_U32 portBase = 0;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -968,14 +965,14 @@
}
// port enable disable test
-TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
+TEST_P(ComponentHidlTest, PortEnableDisable_Idle) {
description("Test Port Enable and Disable (Component State :: Idle)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_U32 portBase = 0;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -1074,14 +1071,14 @@
}
// port enable disable test
-TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
+TEST_P(ComponentHidlTest, PortEnableDisable_Execute) {
description("Test Port Enable and Disable (Component State :: Execute)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_U32 portBase = 0;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -1192,14 +1189,14 @@
}
// port enable disable test - monkeying
-TEST_F(ComponentHidlTest, DISABLED_PortEnableDisable_M) {
+TEST_P(ComponentHidlTest, DISABLED_PortEnableDisable_M) {
description(
"Test Port Enable and Disable Monkeying (Component State :: Loaded)");
if (disableTest || isSecure) return;
android::hardware::media::omx::V1_0::Status status;
OMX_U32 portBase = 0;
Message msg;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
@@ -1267,15 +1264,11 @@
}
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, ComponentHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
+ kTestParameters = getTestParameters("");
::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- }
- return status;
-}
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/master/Android.bp b/media/omx/1.0/vts/functional/master/Android.bp
index cf3f15d..5953eb5 100644
--- a/media/omx/1.0/vts/functional/master/Android.bp
+++ b/media/omx/1.0/vts/functional/master/Android.bp
@@ -18,6 +18,8 @@
name: "VtsHalMediaOmxV1_0TargetMasterTest",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
srcs: ["VtsHalMediaOmxV1_0TargetMasterTest.cpp"],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
-
diff --git a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
index 64abe1c..9b4722e 100644
--- a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
+++ b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
@@ -20,6 +20,7 @@
#endif
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
@@ -29,47 +30,39 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
-using ::android::hardware::media::omx::V1_0::IOmx;
-using ::android::hardware::media::omx::V1_0::IOmxObserver;
-using ::android::hardware::media::omx::V1_0::IOmxNode;
-using ::android::hardware::media::omx::V1_0::IOmxStore;
-using ::android::hardware::media::omx::V1_0::Message;
-using ::android::hardware::media::omx::V1_0::CodecBuffer;
-using ::android::hardware::media::omx::V1_0::PortMode;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::hidl::memory::V1_0::IMapper;
+using ::android::sp;
+using ::android::base::Join;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
+using ::android::hardware::media::omx::V1_0::CodecBuffer;
+using ::android::hardware::media::omx::V1_0::IOmx;
+using ::android::hardware::media::omx::V1_0::IOmxNode;
+using ::android::hardware::media::omx::V1_0::IOmxObserver;
+using ::android::hardware::media::omx::V1_0::IOmxStore;
+using ::android::hardware::media::omx::V1_0::Message;
+using ::android::hardware::media::omx::V1_0::PortMode;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMapper;
+using ::android::hidl::memory::V1_0::IMemory;
-#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_hidl_test_common.h>
-static ComponentTestEnvironment* gEnv = nullptr;
-
-class MasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
- public:
+class MasterHidlTest : public ::testing::TestWithParam<std::string> {
+ public:
virtual void SetUp() override {
- Super::SetUp();
- omxStore = nullptr;
- omxStore = Super::getService<IOmxStore>();
+ omxStore = IOmxStore::getService(GetParam());
ASSERT_NE(omxStore, nullptr);
- omx = nullptr;
- omx = omxStore->getOmx(gEnv->getInstance());
+ omx = IOmx::getService(GetParam());
ASSERT_NE(omx, nullptr);
}
- virtual void TearDown() override {
- Super::TearDown();
- }
-
sp<IOmxStore> omxStore;
sp<IOmx> omx;
@@ -79,6 +72,11 @@
}
};
+struct AttributePattern {
+ const testing::internal::RE key;
+ const testing::internal::RE value;
+};
+
void displayComponentInfo(hidl_vec<IOmx::ComponentInfo>& nodeList) {
for (size_t i = 0; i < nodeList.size(); i++) {
printf("%s | ", nodeList[i].mName.c_str());
@@ -89,8 +87,122 @@
}
}
-// list service attributes
-TEST_F(MasterHidlTest, ListServiceAttr) {
+/*
+ * Returns the role based on is_encoder and mime.
+ *
+ * The mapping from a pair (is_encoder, mime) to a role string is
+ * defined in frameworks/av/media/libmedia/MediaDefs.cpp and
+ * frameworks/av/media/libstagefright/omx/OMXUtils.cpp. This function
+ * does essentially the same work as GetComponentRole() in
+ * OMXUtils.cpp.
+ *
+ * Args:
+ * is_encoder: A boolean indicating whether the role is for an
+ * encoder or a decoder.
+ * mime: A string of the desired mime type.
+ *
+ * Returns:
+ * A const string for the requested role name, empty if mime is not
+ * recognized.
+ */
+const std::string getComponentRole(bool isEncoder, const std::string mime) {
+ // Mapping from mime types to roles.
+ // These values come from MediaDefs.cpp and OMXUtils.cpp
+ const std::map<const std::string, const std::string> audioMimeToRole = {
+ {"3gpp", "amrnb"}, {"ac3", "ac3"}, {"amr-wb", "amrwb"},
+ {"eac3", "eac3"}, {"flac", "flac"}, {"g711-alaw", "g711alaw"},
+ {"g711-mlaw", "g711mlaw"}, {"gsm", "gsm"}, {"mp4a-latm", "aac"},
+ {"mpeg", "mp3"}, {"mpeg-L1", "mp1"}, {"mpeg-L2", "mp2"},
+ {"opus", "opus"}, {"raw", "raw"}, {"vorbis", "vorbis"},
+ };
+ const std::map<const std::string, const std::string> videoMimeToRole = {
+ {"3gpp", "h263"}, {"avc", "avc"}, {"dolby-vision", "dolby-vision"},
+ {"hevc", "hevc"}, {"mp4v-es", "mpeg4"}, {"mpeg2", "mpeg2"},
+ {"x-vnd.on2.vp8", "vp8"}, {"x-vnd.on2.vp9", "vp9"},
+ };
+ const std::map<const std::string, const std::string> imageMimeToRole = {
+ {"vnd.android.heic", "heic"},
+ };
+
+ // Suffix begins after the mime prefix.
+ const size_t prefixEnd = mime.find("/");
+ if (prefixEnd == std::string::npos || prefixEnd == mime.size()) return "";
+ const std::string mime_suffix = mime.substr(prefixEnd + 1, mime.size() - 1);
+ const std::string middle = isEncoder ? "encoder." : "decoder.";
+ std::string prefix;
+ std::string suffix;
+ if (mime.rfind("audio/", 0) != std::string::npos) {
+ const auto it = audioMimeToRole.find(mime_suffix);
+ if (it == audioMimeToRole.end()) return "";
+ prefix = "audio_";
+ suffix = it->second;
+ } else if (mime.rfind("video/", 0) != std::string::npos) {
+ const auto it = videoMimeToRole.find(mime_suffix);
+ if (it == videoMimeToRole.end()) return "";
+ prefix = "video_";
+ suffix = it->second;
+ } else if (mime.rfind("image/", 0) != std::string::npos) {
+ const auto it = imageMimeToRole.find(mime_suffix);
+ if (it == imageMimeToRole.end()) return "";
+ prefix = "image_";
+ suffix = it->second;
+ } else {
+ return "";
+ }
+ return prefix + middle + suffix;
+}
+
+void validateAttributes(
+ const std::map<const std::string, const testing::internal::RE>& knownPatterns,
+ const std::vector<const struct AttributePattern>& unknownPatterns,
+ hidl_vec<IOmxStore::Attribute> attributes) {
+ std::set<const std::string> attributeKeys;
+ for (const auto& attr : attributes) {
+ // Make sure there are no duplicates
+ const auto [nodeIter, inserted] = attributeKeys.insert(attr.key);
+ EXPECT_EQ(inserted, true) << "Attribute \"" << attr.key << "\" has duplicates.";
+
+ // Check the value against the corresponding regular
+ // expression.
+ const auto knownPattern = knownPatterns.find(attr.key);
+ if (knownPattern != knownPatterns.end()) {
+ EXPECT_EQ(testing::internal::RE::FullMatch(attr.value, knownPattern->second), true)
+ << "Attribute \"" << attr.key << "\" has invalid value \"" << attr.value << ".";
+ ;
+ } else {
+ // Failed to find exact attribute, check against
+ // possible patterns.
+ bool keyFound = false;
+ for (const auto& unknownPattern : unknownPatterns) {
+ if (testing::internal::RE::PartialMatch(attr.key, unknownPattern.key)) {
+ keyFound = true;
+ EXPECT_EQ(testing::internal::RE::FullMatch(attr.value, unknownPattern.value),
+ true)
+ << "Attribute \"" << attr.key << "\" has invalid value \"" << attr.value
+ << ".";
+ }
+ }
+ if (!keyFound) {
+ std::cout << "Warning, Unrecognized attribute \"" << attr.key << "\" with value \""
+ << attr.value << "\"." << std::endl;
+ }
+ }
+ }
+}
+
+// Make sure IOmx and IOmxStore have the same set of instances.
+TEST(MasterHidlTest, instanceMatchValidation) {
+ auto omxInstances = android::hardware::getAllHalInstanceNames(IOmx::descriptor);
+ auto omxStoreInstances = android::hardware::getAllHalInstanceNames(IOmxStore::descriptor);
+ ASSERT_EQ(omxInstances.size(), omxInstances.size());
+ for (const std::string& omxInstance : omxInstances) {
+ EXPECT_TRUE(std::find(omxStoreInstances.begin(), omxStoreInstances.end(), omxInstance) !=
+ omxStoreInstances.end());
+ }
+}
+
+// list service attributes and verify expected formats
+TEST_P(MasterHidlTest, ListServiceAttr) {
description("list service attributes");
android::hardware::media::omx::V1_0::Status status;
hidl_vec<IOmxStore::Attribute> attributes;
@@ -103,30 +215,225 @@
})
.isOk());
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
- if (attributes.size() == 0) ALOGV("Warning, Attribute list empty");
+ if (attributes.size() == 0) {
+ std::cout << "Warning, Attribute list empty" << std::endl;
+ } else {
+ /*
+ * knownPatterns is a map whose keys are the known "key" for a service
+ * attribute pair (see IOmxStore::Attribute), and whose values are the
+ * corresponding regular expressions that will have to match with the
+ * "value" of the attribute pair. If listServiceAttributes() returns an
+ * attribute that has a matching key but an unmatched value, the test
+ * will fail.
+ */
+ const std::map<const std::string, const testing::internal::RE> knownPatterns = {
+ {"max-video-encoder-input-buffers", "0|[1-9][0-9]*"},
+ {"supports-multiple-secure-codecs", "0|1"},
+ {"supports-secure-with-non-secure-codec", "0|1"},
+ };
+ /*
+ * unknownPatterns is a vector of pairs of regular expressions.
+ * For each attribute whose key is not known (i.e., does not match any
+ * of the keys in the "knownPatterns" variable defined above), that key will be
+ * tried for a match with the first element of each pair of the variable
+ * "unknownPatterns". If a match occurs, the value of that same attribute will be
+ * tried for a match with the second element of the pair. If this second
+ * match fails, the test will fail.
+ */
+ const std::vector<const struct AttributePattern> unknownPatterns = {
+ {"supports-[a-z0-9-]*", "0|1"}};
+
+ validateAttributes(knownPatterns, unknownPatterns, attributes);
+ }
}
// get node prefix
-TEST_F(MasterHidlTest, getNodePrefix) {
+TEST_P(MasterHidlTest, getNodePrefix) {
description("get node prefix");
hidl_string prefix;
omxStore->getNodePrefix(
[&prefix](hidl_string const& _nl) { prefix = _nl; });
- if (prefix.empty()) ALOGV("Warning, Node Prefix empty");
+ if (prefix.empty()) std::cout << "Warning, Node Prefix empty" << std::endl;
}
-// list roles
-TEST_F(MasterHidlTest, ListRoles) {
+// list roles and validate all RoleInfo objects
+TEST_P(MasterHidlTest, ListRoles) {
description("list roles");
hidl_vec<IOmxStore::RoleInfo> roleList;
omxStore->listRoles([&roleList](hidl_vec<IOmxStore::RoleInfo> const& _nl) {
roleList = _nl;
});
- if (roleList.size() == 0) ALOGV("Warning, RoleInfo list empty");
+ if (roleList.size() == 0) {
+ GTEST_SKIP() << "Warning, RoleInfo list empty";
+ return;
+ }
+
+ // Basic patterns for matching
+ const std::string toggle = "(0|1)";
+ const std::string string = "(.*)";
+ const std::string num = "(0|([1-9][0-9]*))";
+ const std::string size = "(" + num + "x" + num + ")";
+ const std::string ratio = "(" + num + ":" + num + ")";
+ const std::string range_num = "((" + num + "-" + num + ")|" + num + ")";
+ const std::string range_size = "((" + size + "-" + size + ")|" + size + ")";
+ const std::string range_ratio = "((" + ratio + "-" + ratio + ")|" + ratio + ")";
+ const std::string list_range_num = "(" + range_num + "(," + range_num + ")*)";
+
+ // Matching rules for node attributes with fixed keys
+ const std::map<const std::string, const testing::internal::RE> knownPatterns = {
+ {"alignment", size},
+ {"bitrate-range", range_num},
+ {"block-aspect-ratio-range", range_ratio},
+ {"block-count-range", range_num},
+ {"block-size", size},
+ {"blocks-per-second-range", range_num},
+ {"complexity-default", num},
+ {"complexity-range", range_num},
+ {"feature-adaptive-playback", toggle},
+ {"feature-bitrate-control", "(VBR|CBR|CQ)[,(VBR|CBR|CQ)]*"},
+ {"feature-can-swap-width-height", toggle},
+ {"feature-intra-refresh", toggle},
+ {"feature-partial-frame", toggle},
+ {"feature-secure-playback", toggle},
+ {"feature-tunneled-playback", toggle},
+ {"frame-rate-range", range_num},
+ {"max-channel-count", num},
+ {"max-concurrent-instances", num},
+ {"max-supported-instances", num},
+ {"pixel-aspect-ratio-range", range_ratio},
+ {"quality-default", num},
+ {"quality-range", range_num},
+ {"quality-scale", string},
+ {"sample-rate-ranges", list_range_num},
+ {"size-range", range_size},
+ };
+
+ // Strings for matching rules for node attributes with key patterns
+ const std::vector<const struct AttributePattern> unknownPatterns = {
+ {"measured-frame-rate-" + size + "-range", range_num},
+ {"feature-[a-zA-Z0-9_-]+", string},
+ };
+
+ // Matching rules for node names and owners
+ const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9.-]+";
+ const testing::internal::RE nodeOwnerPattern = "[a-zA-Z0-9._-]+";
+
+ std::set<const std::string> roleKeys;
+ std::map<const std::string, std::set<const std::string>> nodeToRoles;
+ std::map<const std::string, std::set<const std::string>> ownerToNodes;
+ for (const IOmxStore::RoleInfo& role : roleList) {
+ // Make sure there are no duplicates
+ const auto [roleIter, inserted] = roleKeys.insert(role.role);
+ EXPECT_EQ(inserted, true) << "Role \"" << role.role << "\" has duplicates.";
+
+ // Make sure role name follows expected format based on type and
+ // isEncoder
+ const std::string role_name = getComponentRole(role.isEncoder, role.type);
+ EXPECT_EQ(role_name, role.role) << "Role \"" << role.role << "\" does not match "
+ << (role.isEncoder ? "an encoder " : "a decoder ")
+ << "for mime type \"" << role.type << ".";
+
+ // Check the nodes for this role
+ std::set<const std::string> nodeKeys;
+ for (const IOmxStore::NodeInfo& node : role.nodes) {
+ // Make sure there are no duplicates
+ const auto [nodeIter, inserted] = nodeKeys.insert(node.name);
+ EXPECT_EQ(inserted, true) << "Node \"" << node.name << "\" has duplicates.";
+
+ // Check the format of node name
+ EXPECT_EQ(testing::internal::RE::FullMatch(node.name, nodeNamePattern), true)
+ << "Node name \"" << node.name << " is invalid.";
+ // Check the format of node owner
+ EXPECT_EQ(testing::internal::RE::FullMatch(node.owner, nodeOwnerPattern), true)
+ << "Node owner \"" << node.owner << " is invalid.";
+
+ validateAttributes(knownPatterns, unknownPatterns, node.attributes);
+
+ ownerToNodes[node.owner].insert(node.name);
+ nodeToRoles[node.name].insert(role.role);
+ }
+ }
+
+ // Verify the information with IOmx::listNodes().
+ // IOmxStore::listRoles() and IOmx::listNodes() should give consistent
+ // information about nodes and roles.
+ for (const auto& [owner, nodes] : ownerToNodes) {
+ // Obtain the IOmx instance for each "owner"
+ const sp<IOmx> omx = omxStore->getOmx(owner);
+ EXPECT_NE(nullptr, omx);
+
+ // Invoke IOmx::listNodes()
+ android::hardware::media::omx::V1_0::Status status;
+ hidl_vec<IOmx::ComponentInfo> nodeList;
+ EXPECT_TRUE(
+ omx->listNodes([&status, &nodeList](android::hardware::media::omx::V1_0::Status _s,
+ hidl_vec<IOmx::ComponentInfo> const& _nl) {
+ status = _s;
+ nodeList = _nl;
+ }).isOk());
+ ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+
+ // Verify that roles for each node match with the information from
+ // IOmxStore::listRoles().
+ std::set<const std::string> nodeKeys;
+ for (IOmx::ComponentInfo node : nodeList) {
+ // Make sure there are no duplicates
+ const auto [nodeIter, inserted] = nodeKeys.insert(node.mName);
+ EXPECT_EQ(inserted, true)
+ << "IOmx::listNodes() lists duplicate nodes \"" << node.mName << "\".";
+
+ // Skip "hidden" nodes, i.e. those that are not advertised by
+ // IOmxStore::listRoles().
+ if (nodes.find(node.mName) == nodes.end()) {
+ std::cout << "Warning, IOmx::listNodes() lists unknown node \"" << node.mName
+ << "\" for IOmx instance \"" << owner << "\"." << std::endl;
+ continue;
+ }
+
+ // All the roles advertised by IOmxStore::listRoles() for this
+ // node must be included in roleKeys.
+ std::set<const std::string> difference;
+ std::set_difference(nodeToRoles[node.mName].begin(), nodeToRoles[node.mName].end(),
+ roleKeys.begin(), roleKeys.end(),
+ std::inserter(difference, difference.begin()));
+ EXPECT_EQ(difference.empty(), true) << "IOmx::listNodes() for IOmx "
+ "instance \""
+ << owner
+ << "\" does not report some "
+ "expected nodes: "
+ << android::base::Join(difference, ", ") << ".";
+ }
+ // Check that all nodes obtained from IOmxStore::listRoles() are
+ // supported by the their corresponding IOmx instances.
+ std::set<const std::string> difference;
+ std::set_difference(nodes.begin(), nodes.end(), nodeKeys.begin(), nodeKeys.end(),
+ std::inserter(difference, difference.begin()));
+ EXPECT_EQ(difference.empty(), true) << "IOmx::listNodes() for IOmx "
+ "instance \""
+ << owner
+ << "\" does not report some "
+ "expected nodes: "
+ << android::base::Join(difference, ", ") << ".";
+ }
+
+ if (!nodeToRoles.empty()) {
+ // Check that the prefix is a sensible string.
+ hidl_string prefix;
+ omxStore->getNodePrefix([&prefix](hidl_string const& _nl) { prefix = _nl; });
+ EXPECT_EQ(testing::internal::RE::PartialMatch(prefix, nodeNamePattern), true)
+ << "\"" << prefix << "\" is not a valid prefix for node names.";
+
+ // Check that all node names have the said prefix.
+ for (const auto& node : nodeToRoles) {
+ EXPECT_NE(node.first.rfind(prefix, 0), std::string::npos)
+ << "Node \"" << node.first << "\" does not start with prefix \"" << prefix
+ << "\".";
+ }
+ }
}
// list components and roles.
-TEST_F(MasterHidlTest, ListNodes) {
+TEST_P(MasterHidlTest, ListNodes) {
description("enumerate component and roles");
android::hardware::media::omx::V1_0::Status status;
hidl_vec<IOmx::ComponentInfo> nodeList;
@@ -141,7 +448,7 @@
.isOk());
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
if (nodeList.size() == 0)
- ALOGV("Warning, ComponentInfo list empty");
+ std::cout << "Warning, ComponentInfo list empty" << std::endl;
else {
// displayComponentInfo(nodeList);
for (size_t i = 0; i < nodeList.size(); i++) {
@@ -174,15 +481,7 @@
EXPECT_TRUE(isPass);
}
-int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- }
- return status;
-}
+INSTANTIATE_TEST_CASE_P(
+ PerInstance, MasterHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IOmxStore::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/media/omx/1.0/vts/functional/video/Android.bp b/media/omx/1.0/vts/functional/video/Android.bp
index c7e0424..b35c26c 100644
--- a/media/omx/1.0/vts/functional/video/Android.bp
+++ b/media/omx/1.0/vts/functional/video/Android.bp
@@ -16,23 +16,33 @@
cc_test {
name: "VtsHalMediaOmxV1_0TargetVideoDecTest",
+ stem: "vts_hal_media_omx_v1_0_video_dec_test",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
srcs: [
"VtsHalMediaOmxV1_0TargetVideoDecTest.cpp",
- "media_video_hidl_test_common.cpp"
+ "media_video_hidl_test_common.cpp",
],
- test_suites: ["general-tests"],
+ data: [":media_omx_video_res"],
+ test_config: "VtsHalMediaOmxV1_0TargetVideoDecTest.xml",
+ test_suites: [
+ "vts",
+ ],
}
cc_test {
name: "VtsHalMediaOmxV1_0TargetVideoEncTest",
+ stem: "vts_hal_media_omx_v1_0_video_enc_test",
defaults: ["VtsHalMediaOmxV1_0Defaults"],
srcs: [
"VtsHalMediaOmxV1_0TargetVideoEncTest.cpp",
- "media_video_hidl_test_common.cpp"
+ "media_video_hidl_test_common.cpp",
],
static_libs: [
"libnativewindow",
],
- test_suites: ["general-tests"],
+ data: [":media_omx_video_res"],
+ test_config: "VtsHalMediaOmxV1_0TargetVideoEncTest.xml",
+ test_suites: [
+ "vts",
+ ],
}
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
index df048c6..29a32a5 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
@@ -28,6 +28,8 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
@@ -44,49 +46,46 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media/hardware/HardwareAPI.h>
-#include <media_hidl_test_common.h>
#include <media_video_hidl_test_common.h>
#include <fstream>
-static ComponentTestEnvironment* gEnv = nullptr;
+// Resource directory
+std::string sResourceDir = "";
// video decoder test fixture class
-class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Role: " + gEnv->getRole().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
+class VideoDecHidlTest
+ : public ::testing::TestWithParam<std::tuple<std::string, std::string, std::string>> {
+ public:
+ ::std::string getTestCaseInfo() const {
+ return ::std::string() + "Component: " + component_ + " | " + "Role: " + role_ + " | " +
+ "Instance: " + instance_ + " | " + "Res: " + sResourceDir;
}
virtual void SetUp() override {
- Super::SetUp();
+ instance_ = std::get<0>(GetParam());
+ component_ = std::get<1>(GetParam());
+ role_ = std::get<2>(GetParam());
+ ASSERT_NE(sResourceDir.empty(), true);
+
disableTest = false;
android::hardware::media::omx::V1_0::Status status;
- omx = Super::getService<IOmx>(gEnv->getInstance());
+ omx = IOmx::getService(instance_);
ASSERT_NE(omx, nullptr);
observer =
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
handleMessage(msg, buffer);
});
ASSERT_NE(observer, nullptr);
- if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
- disableTest = true;
- EXPECT_TRUE(omx->allocateNode(
- gEnv->getComponent(), observer,
- [&](android::hardware::media::omx::V1_0::Status _s,
- sp<IOmxNode> const& _nl) {
- status = _s;
- this->omxNode = _nl;
- })
- .isOk());
+ if (component_.find("OMX.") != 0) disableTest = true;
+ EXPECT_TRUE(omx->allocateNode(component_, observer,
+ [&](android::hardware::media::omx::V1_0::Status _s,
+ sp<IOmxNode> const& _nl) {
+ status = _s;
+ this->omxNode = _nl;
+ })
+ .isOk());
if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
disableTest = true;
std::cout << "[ WARN ] Test Disabled, component not present\n";
@@ -94,7 +93,7 @@
}
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
ASSERT_NE(omxNode, nullptr);
- ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
+ ASSERT_NE(role_.empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
@@ -107,7 +106,7 @@
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
- strcpy(substring, gEnv->getRole().c_str());
+ strcpy(substring, role_.c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
@@ -146,11 +145,8 @@
isSecure = false;
portSettingsChange = false;
size_t suffixLen = strlen(".secure");
- if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
- isSecure =
- !strcmp(gEnv->getComponent().c_str() +
- strlen(gEnv->getComponent().c_str()) - suffixLen,
- ".secure");
+ if (component_.rfind(".secure") == component_.length() - suffixLen) {
+ isSecure = true;
}
if (isSecure) disableTest = true;
omxNode->configureVideoTunnelMode(
@@ -175,7 +171,6 @@
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
- Super::TearDown();
}
// callback function to process messages received by onMessages() from IL
@@ -255,6 +250,10 @@
unknown_comp,
};
+ std::string component_;
+ std::string role_;
+ std::string instance_;
+
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
@@ -719,23 +718,23 @@
}
// set component role
-TEST_F(VideoDecHidlTest, SetRole) {
+TEST_P(VideoDecHidlTest, SetRole) {
description("Test Set Component Role");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// port format enumeration
-TEST_F(VideoDecHidlTest, EnumeratePortFormat) {
+TEST_P(VideoDecHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
OMX_U32 xFramerate = (24U << 16);
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -755,12 +754,12 @@
// test port settings reconfiguration, elementary stream decode and timestamp
// deviation
-TEST_F(VideoDecHidlTest, DecodeTest) {
+TEST_P(VideoDecHidlTest, DecodeTest) {
description("Tests Port Reconfiguration, Decode and timestamp deviation");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -770,8 +769,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -860,7 +859,7 @@
}
// Test for adaptive playback support
-TEST_F(VideoDecHidlTest, AdaptivePlaybackTest) {
+TEST_P(VideoDecHidlTest, AdaptivePlaybackTest) {
description("Tests for Adaptive Playback support");
if (disableTest) return;
if (!(compName == avc || compName == hevc || compName == vp8 ||
@@ -868,7 +867,7 @@
return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -895,7 +894,7 @@
uint32_t adaptiveMaxHeight = 240;
status = omxNode->prepareForAdaptivePlayback(
kPortIndexOutput, true, adaptiveMaxWidth, adaptiveMaxHeight);
- if (strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11) == 0) {
+ if (component_.find("OMX.google.") == 0) {
// SoftOMX Decoders donot support graphic buffer modes. So for them
// support for adaptive play back is mandatory in Byte Buffer mode
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
@@ -944,8 +943,8 @@
std::ifstream eleStream, eleInfo;
char mURL[512], info[512];
android::Vector<FrameData> Info;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info, i % STREAM_COUNT);
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true);
@@ -1008,12 +1007,12 @@
}
// end of sequence test
-TEST_F(VideoDecHidlTest, EOSTest_M) {
+TEST_P(VideoDecHidlTest, EOSTest_M) {
description("Test End of stream monkeying");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1074,12 +1073,12 @@
}
// end of sequence test
-TEST_F(VideoDecHidlTest, ThumbnailTest) {
+TEST_P(VideoDecHidlTest, ThumbnailTest) {
description("Test Request for thumbnail");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1089,8 +1088,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -1195,12 +1194,12 @@
}
// end of sequence test
-TEST_F(VideoDecHidlTest, SimpleEOSTest) {
+TEST_P(VideoDecHidlTest, SimpleEOSTest) {
description("Test End of stream");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1210,8 +1209,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -1302,12 +1301,12 @@
}
// test input/output port flush
-TEST_F(VideoDecHidlTest, FlushTest) {
+TEST_P(VideoDecHidlTest, FlushTest) {
description("Test Flush");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1317,8 +1316,8 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512], info[512];
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(compName, mURL, info);
std::ifstream eleStream, eleInfo;
@@ -1420,15 +1419,21 @@
kPortIndexOutput));
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, VideoDecHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
+ kTestParameters = getTestParameters("video_decoder");
::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
}
- return status;
-}
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.xml b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.xml
new file mode 100644
index 0000000..a2fd92a
--- /dev/null
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalMediaOmxV1_0TargetVideoDecTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_hal_media_omx_v1_0_video_dec_test" value="/data/local/tmp/vts_hal_media_omx_v1_0_video_dec_test" />
+
+ <!-- Files used for video testing -->
+ <option name="push-file" key="bbb_352x288_420p_30fps_32frames.yuv" value="/data/local/tmp/media/bbb_352x288_420p_30fps_32frames.yuv" />
+ <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.h264" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.h264" />
+ <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.info" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.info" />
+ <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.h264" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.h264" />
+ <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.info" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.info" />
+ <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.h263" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.h263" />
+ <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.info" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.info" />
+ <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.hevc" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.hevc" />
+ <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.info" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.info" />
+ <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.hevc" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.hevc" />
+ <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.info" />
+ <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.info" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.info" />
+ <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.m2v" />
+ <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.info" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.info" />
+ <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.m2v" />
+ <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.info" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.info" />
+ <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.m4v" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.m4v" />
+ <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.info" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.info" />
+ <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.vp8" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.vp8" />
+ <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.info" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.info" />
+ <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.vp8" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.vp8" />
+ <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.info" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.info" />
+ <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.vp9" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.vp9" />
+ <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.info" />
+ <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.vp9" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.vp9" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_hal_media_omx_v1_0_video_dec_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index 2280cee..4b469e6 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -34,6 +34,8 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
using ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer;
using ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener;
@@ -56,51 +58,48 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media/hardware/HardwareAPI.h>
-#include <media_hidl_test_common.h>
#include <media_video_hidl_test_common.h>
#include <system/window.h>
#include <fstream>
#include <variant>
-static ComponentTestEnvironment* gEnv = nullptr;
+// Resource directory
+std::string sResourceDir = "";
// video encoder test fixture class
-class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Role: " + gEnv->getRole().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
+class VideoEncHidlTest
+ : public ::testing::TestWithParam<std::tuple<std::string, std::string, std::string>> {
+ public:
+ ::std::string getTestCaseInfo() const {
+ return ::std::string() + "Component: " + component_ + " | " + "Role: " + role_ + " | " +
+ "Instance: " + instance_ + " | " + "Res: " + sResourceDir;
}
virtual void SetUp() override {
- Super::SetUp();
+ instance_ = std::get<0>(GetParam());
+ component_ = std::get<1>(GetParam());
+ role_ = std::get<2>(GetParam());
+ ASSERT_NE(sResourceDir.empty(), true);
+
disableTest = false;
android::hardware::media::omx::V1_0::Status status;
- omx = Super::getService<IOmx>(gEnv->getInstance());
+ omx = IOmx::getService(instance_);
ASSERT_NE(omx, nullptr);
observer =
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
handleMessage(msg, buffer);
});
ASSERT_NE(observer, nullptr);
- if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
- disableTest = true;
- EXPECT_TRUE(omx->allocateNode(
- gEnv->getComponent(), observer,
- [&](android::hardware::media::omx::V1_0::Status _s,
- sp<IOmxNode> const& _nl) {
- status = _s;
- this->omxNode = _nl;
- })
- .isOk());
+ if (component_.find("OMX.") != 0) disableTest = true;
+ EXPECT_TRUE(omx->allocateNode(component_, observer,
+ [&](android::hardware::media::omx::V1_0::Status _s,
+ sp<IOmxNode> const& _nl) {
+ status = _s;
+ this->omxNode = _nl;
+ })
+ .isOk());
if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
disableTest = true;
std::cout << "[ WARN ] Test Disabled, component not present\n";
@@ -108,7 +107,7 @@
}
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
ASSERT_NE(omxNode, nullptr);
- ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
+ ASSERT_NE(role_.empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
@@ -121,7 +120,7 @@
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
- strcpy(substring, gEnv->getRole().c_str());
+ strcpy(substring, role_.c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
@@ -158,11 +157,8 @@
source = nullptr;
isSecure = false;
size_t suffixLen = strlen(".secure");
- if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
- isSecure =
- !strcmp(gEnv->getComponent().c_str() +
- strlen(gEnv->getComponent().c_str()) - suffixLen,
- ".secure");
+ if (component_.rfind(".secure") == component_.length() - suffixLen) {
+ isSecure = true;
}
if (isSecure) disableTest = true;
if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
@@ -177,7 +173,6 @@
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
- Super::TearDown();
}
// callback function to process messages received by onMessages() from IL
@@ -245,6 +240,10 @@
unknown_comp,
};
+ std::string component_;
+ std::string role_;
+ std::string instance_;
+
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
@@ -1085,23 +1084,23 @@
}
// set component role
-TEST_F(VideoEncHidlTest, SetRole) {
+TEST_P(VideoEncHidlTest, SetRole) {
description("Test Set Component Role");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// port format enumeration
-TEST_F(VideoEncHidlTest, EnumeratePortFormat) {
+TEST_P(VideoEncHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
OMX_U32 xFramerate = (30U << 16);
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1121,12 +1120,12 @@
}
// Test IOmxBufferSource CallBacks
-TEST_F(VideoEncHidlTest, BufferSourceCallBacks) {
+TEST_P(VideoEncHidlTest, BufferSourceCallBacks) {
description("Test IOmxBufferSource CallBacks");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1178,12 +1177,12 @@
}
// test raw stream encode (input is byte buffers)
-TEST_F(VideoEncHidlTest, EncodeTest) {
+TEST_P(VideoEncHidlTest, EncodeTest) {
description("Test Encode");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1193,7 +1192,7 @@
kPortIndexOutput = kPortIndexInput + 1;
}
char mURL[512];
- strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
GetURLForComponent(mURL);
std::ifstream eleStream;
@@ -1293,12 +1292,12 @@
}
// test raw stream encode (input is ANW buffers)
-TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
+TEST_P(VideoEncHidlTest, EncodeTestBufferMetaModes) {
description("Test Encode Input buffer metamodes");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1383,7 +1382,7 @@
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
char mURL[512];
- strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
GetURLForComponent(mURL);
uint32_t latency = 0;
@@ -1460,12 +1459,12 @@
}
// Test end of stream
-TEST_F(VideoEncHidlTest, EncodeTestEOS) {
+TEST_P(VideoEncHidlTest, EncodeTestEOS) {
description("Test EOS");
if (disableTest) return;
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
- status = setRole(omxNode, gEnv->getRole().c_str());
+ status = setRole(omxNode, role_);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
@@ -1574,15 +1573,21 @@
ASSERT_EQ(returnval, 0);
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, VideoEncHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
+ kTestParameters = getTestParameters("video_encoder");
::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
}
- return status;
-}
+
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.xml b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.xml
new file mode 100644
index 0000000..57ba1e4
--- /dev/null
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalMediaOmxV1_0TargetVideoEncTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_hal_media_omx_v1_0_video_enc_test" value="/data/local/tmp/vts_hal_media_omx_v1_0_video_enc_test" />
+
+ <!-- Files used for video testing -->
+ <option name="push-file" key="bbb_352x288_420p_30fps_32frames.yuv" value="/data/local/tmp/media/bbb_352x288_420p_30fps_32frames.yuv" />
+ <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.h264" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.h264" />
+ <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.info" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.info" />
+ <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.h264" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.h264" />
+ <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.info" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.info" />
+ <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.h263" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.h263" />
+ <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.info" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.info" />
+ <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.hevc" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.hevc" />
+ <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.info" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.info" />
+ <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.hevc" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.hevc" />
+ <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.info" />
+ <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.info" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.info" />
+ <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.m2v" />
+ <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.info" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.info" />
+ <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.m2v" />
+ <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.info" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.info" />
+ <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.m4v" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.m4v" />
+ <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.info" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.info" />
+ <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.vp8" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.vp8" />
+ <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.info" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.info" />
+ <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.vp8" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.vp8" />
+ <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.info" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.info" />
+ <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.vp9" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.vp9" />
+ <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.info" />
+ <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.vp9" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.vp9" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_hal_media_omx_v1_0_video_enc_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp
index e1b6022..5e2c107 100644
--- a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.cpp
@@ -44,7 +44,6 @@
using ::android::hardware::hidl_string;
using ::android::sp;
-#include <VtsHalHidlTargetTestBase.h>
#include <hidlmemory/mapping.h>
#include <media/hardware/HardwareAPI.h>
#include <media_hidl_test_common.h>
diff --git a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
index 55de125..e8f5172 100644
--- a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
@@ -17,6 +17,8 @@
#ifndef MEDIA_VIDEO_HIDL_TEST_COMMON_H
#define MEDIA_VIDEO_HIDL_TEST_COMMON_H
+#include <media_hidl_test_common.h>
+
/*
* Common video utils
*/
diff --git a/memtrack/1.0/vts/functional/Android.bp b/memtrack/1.0/vts/functional/Android.bp
index 9e5cf6d..445770a 100644
--- a/memtrack/1.0/vts/functional/Android.bp
+++ b/memtrack/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalMemtrackV1_0TargetTest.cpp"],
static_libs: ["android.hardware.memtrack@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 03af671..87e8519 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -88,5 +88,5 @@
header_libs: [
"libneuralnetworks_headers",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 9ba1925..9afa0af 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -47,5 +47,5 @@
header_libs: [
"libneuralnetworks_headers",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 7c1faee..481eb80 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -72,6 +72,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
index 35275b4..56f3c0b 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -350,7 +350,7 @@
outputTypesList = {OutputType::FULLY_SPECIFIED};
measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
- memoryTypeList = {MemoryType::ASHMEM, MemoryType::BLOB_AHWB};
+ memoryTypeList = {MemoryType::ASHMEM};
}
for (const OutputType outputType : outputTypesList) {
diff --git a/neuralnetworks/1.3/IPreparedModel.hal b/neuralnetworks/1.3/IPreparedModel.hal
index a1814b5..e7d63f4 100644
--- a/neuralnetworks/1.3/IPreparedModel.hal
+++ b/neuralnetworks/1.3/IPreparedModel.hal
@@ -92,13 +92,11 @@
* executing a {@link OperationType::WHILE}
* operation. If a loop condition model does not
* output false within this duration, the
- * execution must be aborted. If the model
- * contains a {@link OperationType::WHILE}
- * operation and no loop timeout duration is
- * provided, the maximum amount of time is {@link
- * LoopTimeoutDurationNs::DEFAULT}. When
- * provided, the duration must not exceed {@link
- * LoopTimeoutDurationNs::MAXIMUM}.
+ * execution must be aborted. If no loop timeout
+ * duration is provided, the maximum amount of
+ * time is {@link LoopTimeoutDurationNs::DEFAULT}.
+ * When provided, the duration must not exceed
+ * {@link LoopTimeoutDurationNs::MAXIMUM}.
* @param callback A callback object used to return the error status of
* the execution, shape information of model output operands, and
* duration of execution. The callback object's notify function must
@@ -170,13 +168,11 @@
* executing a {@link OperationType::WHILE}
* operation. If a loop condition model does not
* output false within this duration, the
- * execution must be aborted. If the model
- * contains a {@link OperationType::WHILE}
- * operation and no loop timeout duration is
- * provided, the maximum amount of time is {@link
- * LoopTimeoutDurationNs::DEFAULT}. When
- * provided, the duration must not exceed {@link
- * LoopTimeoutDurationNs::MAXIMUM}.
+ * execution must be aborted. If no loop timeout
+ * duration is provided, the maximum amount of
+ * time is {@link LoopTimeoutDurationNs::DEFAULT}.
+ * When provided, the duration must not exceed
+ * {@link LoopTimeoutDurationNs::MAXIMUM}.
* @return status Error status of the execution, must be:
* - NONE if execution is performed successfully
* - DEVICE_UNAVAILABLE if driver is offline or busy
@@ -258,13 +254,11 @@
* executing a {@link OperationType::WHILE}
* operation. If a loop condition model does not
* output false within this duration, the
- * execution must be aborted. If the model
- * contains a {@link OperationType::WHILE}
- * operation and no loop timeout duration is
- * provided, the maximum amount of time is {@link
- * LoopTimeoutDurationNs::DEFAULT}. When
- * provided, the duration must not exceed {@link
- * LoopTimeoutDurationNs::MAXIMUM}.
+ * execution must be aborted. If no loop timeout
+ * duration is provided, the maximum amount of
+ * time is {@link LoopTimeoutDurationNs::DEFAULT}.
+ * When provided, the duration must not exceed
+ * {@link LoopTimeoutDurationNs::MAXIMUM}.
* @param duration The length of time within which the execution is expected
* to complete after all sync fences in waitFor are signaled.
* If the execution cannot be finished within the duration,
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 545a5be..2c1be0b 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -77,5 +77,8 @@
header_libs: [
"libneuralnetworks_headers",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 4c0100e..e590fda 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -535,13 +535,18 @@
removeValueAndDecrementGreaterValues(&model->main.outputIndexes, index);
}
-static bool removeOperandSkip(size_t operand, const Model& model) {
+static bool removeOperandSkip(size_t operandIndex, const Model& model) {
+ const Operand& operand = model.main.operands[operandIndex];
+ if (operand.numberOfConsumers == 0) {
+ // Removing an unused operand has no effect.
+ return true;
+ }
for (const Operation& operation : model.main.operations) {
// Skip removeOperandTest for the following operations.
// - SPLIT's outputs are not checked during prepareModel.
if (operation.type == OperationType::SPLIT) {
- for (const size_t outOprand : operation.outputs) {
- if (operand == outOprand) {
+ for (const size_t index : operation.outputs) {
+ if (index == operandIndex) {
return true;
}
}
@@ -556,8 +561,8 @@
operation.type == OperationType::UNIDIRECTIONAL_SEQUENCE_RNN ||
operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_LSTM ||
operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) {
- for (const size_t outOprand : operation.outputs) {
- if (operand == outOprand) {
+ for (const size_t index : operation.outputs) {
+ if (index == operandIndex) {
return true;
}
}
diff --git a/nfc/1.0/vts/functional/Android.bp b/nfc/1.0/vts/functional/Android.bp
index 40b82bb..40ba22e 100644
--- a/nfc/1.0/vts/functional/Android.bp
+++ b/nfc/1.0/vts/functional/Android.bp
@@ -21,5 +21,5 @@
static_libs: [
"android.hardware.nfc@1.0",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/nfc/1.1/vts/functional/Android.bp b/nfc/1.1/vts/functional/Android.bp
index 8da0ce3..1c18418 100644
--- a/nfc/1.1/vts/functional/Android.bp
+++ b/nfc/1.1/vts/functional/Android.bp
@@ -22,5 +22,5 @@
"android.hardware.nfc@1.0",
"android.hardware.nfc@1.1",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/nfc/1.2/vts/functional/Android.bp b/nfc/1.2/vts/functional/Android.bp
index 7b50a36..83e7a8e 100644
--- a/nfc/1.2/vts/functional/Android.bp
+++ b/nfc/1.2/vts/functional/Android.bp
@@ -23,5 +23,5 @@
"android.hardware.nfc@1.1",
"android.hardware.nfc@1.2",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/oemlock/1.0/vts/functional/Android.bp b/oemlock/1.0/vts/functional/Android.bp
index 90de347..4dd92b5 100644
--- a/oemlock/1.0/vts/functional/Android.bp
+++ b/oemlock/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalOemLockV1_0TargetTest.cpp"],
static_libs: ["android.hardware.oemlock@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/power/1.0/vts/functional/Android.bp b/power/1.0/vts/functional/Android.bp
index 5d5676d..27b9456 100644
--- a/power/1.0/vts/functional/Android.bp
+++ b/power/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalPowerV1_0TargetTest.cpp"],
static_libs: ["android.hardware.power@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
index ba08ee7..7e0ae9c 100644
--- a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
+++ b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
@@ -19,6 +19,8 @@
#include <cutils/properties.h>
+#include <android-base/file.h>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <android/hardware/power/1.0/IPower.h>
#include <gtest/gtest.h>
@@ -73,26 +75,16 @@
TEST_P(PowerHidlTest, TryDifferentGovernors) {
Return<void> ret;
- unique_fd fd1(open(CPU_GOVERNOR_PATH, O_RDWR));
- unique_fd fd2(open(AVAILABLE_GOVERNORS_PATH, O_RDONLY));
- if (fd1 < 0 || fd2 < 0) {
+ std::string old_governor, governors;
+ if (!android::base::ReadFileToString(CPU_GOVERNOR_PATH, &old_governor) ||
+ !android::base::ReadFileToString(AVAILABLE_GOVERNORS_PATH, &governors)) {
// Files don't exist, so skip the rest of the test case
SUCCEED();
return;
}
-
- char old_governor[80];
- ASSERT_LE(0, read(fd1, old_governor, 80));
-
- char governors[1024];
- unsigned len = read(fd2, governors, 1024);
- ASSERT_LE(0u, len);
- governors[len] = '\0';
-
- char *saveptr;
- char *name = strtok_r(governors, " \n", &saveptr);
- while (name) {
- ASSERT_LE(0, write(fd1, name, strlen(name)));
+ auto all_governors = android::base::Split(governors, " \n");
+ for (const auto &governor : all_governors) {
+ ASSERT_TRUE(android::base::WriteStringToFile(governor, CPU_GOVERNOR_PATH));
ret = power->setInteractive(true);
ASSERT_TRUE(ret.isOk());
@@ -104,11 +96,9 @@
power->powerHint(PowerHint::LAUNCH, 1);
power->powerHint(PowerHint::LAUNCH, 0);
-
- name = strtok_r(NULL, " \n", &saveptr);
}
- ASSERT_LE(0, write(fd1, old_governor, strlen(old_governor)));
+ ASSERT_TRUE(android::base::WriteStringToFile(old_governor, CPU_GOVERNOR_PATH));
}
// Sanity check Power::powerHint on good and bad inputs.
diff --git a/power/1.1/vts/functional/Android.bp b/power/1.1/vts/functional/Android.bp
index d9a32df..2860fdb 100644
--- a/power/1.1/vts/functional/Android.bp
+++ b/power/1.1/vts/functional/Android.bp
@@ -22,5 +22,5 @@
"android.hardware.power@1.0",
"android.hardware.power@1.1",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/power/1.2/vts/functional/Android.bp b/power/1.2/vts/functional/Android.bp
index 5385faa..5d1b2a4 100644
--- a/power/1.2/vts/functional/Android.bp
+++ b/power/1.2/vts/functional/Android.bp
@@ -23,5 +23,5 @@
"android.hardware.power@1.1",
"android.hardware.power@1.2",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/power/1.3/vts/functional/Android.bp b/power/1.3/vts/functional/Android.bp
index 77e8619..d8e1c05 100644
--- a/power/1.3/vts/functional/Android.bp
+++ b/power/1.3/vts/functional/Android.bp
@@ -24,5 +24,5 @@
"android.hardware.power@1.2",
"android.hardware.power@1.3",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index 2a6cf94..4008652 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -29,4 +29,5 @@
},
},
},
+ versions: ["1"],
}
diff --git a/power/aidl/aidl_api/android.hardware.power/1/.hash b/power/aidl/aidl_api/android.hardware.power/1/.hash
new file mode 100644
index 0000000..3baf095
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/1/.hash
@@ -0,0 +1 @@
+d5bbe80a8c4df49931e8453f3138820e82dc525c
diff --git a/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/Boost.aidl
new file mode 100644
index 0000000..aced215
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/Boost.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum Boost {
+ INTERACTION = 0,
+ DISPLAY_UPDATE_IMMINENT = 1,
+ ML_ACC = 2,
+ AUDIO_LAUNCH = 3,
+ CAMERA_LAUNCH = 4,
+ CAMERA_SHOT = 5,
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/IPower.aidl
new file mode 100644
index 0000000..8a06623
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/IPower.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+interface IPower {
+ oneway void setMode(in android.hardware.power.Mode type, in boolean enabled);
+ boolean isModeSupported(in android.hardware.power.Mode type);
+ oneway void setBoost(in android.hardware.power.Boost type, in int durationMs);
+ boolean isBoostSupported(in android.hardware.power.Boost type);
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/Mode.aidl
new file mode 100644
index 0000000..f7c2552
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/1/android/hardware/power/Mode.aidl
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum Mode {
+ DOUBLE_TAP_TO_WAKE = 0,
+ LOW_POWER = 1,
+ SUSTAINED_PERFORMANCE = 2,
+ FIXED_PERFORMANCE = 3,
+ VR = 4,
+ LAUNCH = 5,
+ EXPENSIVE_RENDERING = 6,
+ INTERACTIVE = 7,
+ DEVICE_IDLE = 8,
+ DISPLAY_INACTIVE = 9,
+ AUDIO_STREAMING_LOW_LATENCY = 10,
+ CAMERA_STREAMING_SECURE = 11,
+ CAMERA_STREAMING_LOW = 12,
+ CAMERA_STREAMING_MID = 13,
+ CAMERA_STREAMING_HIGH = 14,
+}
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index 7726fd8..28b08c7 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -26,6 +26,6 @@
"android.hardware.power-cpp",
],
test_suites: [
- "vts-core",
+ "vts",
],
}
diff --git a/power/stats/1.0/vts/functional/Android.bp b/power/stats/1.0/vts/functional/Android.bp
index ab47061..d5f1da2 100644
--- a/power/stats/1.0/vts/functional/Android.bp
+++ b/power/stats/1.0/vts/functional/Android.bp
@@ -33,5 +33,5 @@
"libfmq",
"libutils",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/radio/1.0/vts/functional/Android.bp b/radio/1.0/vts/functional/Android.bp
index 2351d90..13fc542 100644
--- a/radio/1.0/vts/functional/Android.bp
+++ b/radio/1.0/vts/functional/Android.bp
@@ -34,7 +34,7 @@
"android.hardware.radio@1.0",
],
test_config: "vts_hal_radio_target_test.xml",
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
cc_test {
@@ -49,7 +49,7 @@
"android.hardware.radio@1.0",
],
test_config: "vts_hal_sap_target_test.xml",
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
cc_library_static {
diff --git a/radio/1.1/vts/functional/Android.bp b/radio/1.1/vts/functional/Android.bp
index 58aa67e..e1278b9 100644
--- a/radio/1.1/vts/functional/Android.bp
+++ b/radio/1.1/vts/functional/Android.bp
@@ -30,5 +30,5 @@
header_libs: [
"radio.util.header@1.0",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/radio/1.2/vts/functional/Android.bp b/radio/1.2/vts/functional/Android.bp
index f7189a8..56f2d5f 100644
--- a/radio/1.2/vts/functional/Android.bp
+++ b/radio/1.2/vts/functional/Android.bp
@@ -34,5 +34,5 @@
"android.hardware.radio.config@1.1",
],
header_libs: ["radio.util.header@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/radio/1.3/vts/functional/Android.bp b/radio/1.3/vts/functional/Android.bp
index 2301732..e32258f 100644
--- a/radio/1.3/vts/functional/Android.bp
+++ b/radio/1.3/vts/functional/Android.bp
@@ -32,5 +32,5 @@
"android.hardware.radio@1.0",
],
header_libs: ["radio.util.header@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
index ca64305..1a01b28 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
@@ -16,6 +16,7 @@
#include <radio_hidl_hal_utils_v1_3.h>
#include <vector>
+#include "VtsCoreUtil.h"
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
@@ -25,6 +26,15 @@
TEST_P(RadioHidlTest_v1_3, enableModem) {
serial = GetRandomSerialNumber();
+ bool isMultiSimEnabled =
+ testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config",
+ "dsds") ||
+ testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "tsts");
+ if (!isMultiSimEnabled) {
+ ALOGI("enableModem, no need to test in single SIM mode");
+ return;
+ }
+
bool responseToggle = radioRsp_v1_3->enableModemResponseToggle;
Return<void> res = radio_v1_3->enableModem(serial, true);
ASSERT_OK(res);
diff --git a/radio/1.3/vts/functional/radio_hidl_hal_test.cpp b/radio/1.3/vts/functional/radio_hidl_hal_test.cpp
index 4581350..c6e5550 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_test.cpp
@@ -38,9 +38,6 @@
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_3->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial);
EXPECT_EQ(RadioError::NONE, radioRsp_v1_3->rspInfo.error);
-
- /* Enforce Vts Testing with Sim Status Present only. */
- EXPECT_EQ(CardState::PRESENT, cardStatus.base.cardState);
}
/*
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
index 8284404..369b55b 100644
--- a/radio/1.4/vts/functional/Android.bp
+++ b/radio/1.4/vts/functional/Android.bp
@@ -35,5 +35,5 @@
"android.hardware.radio.config@1.1",
],
header_libs: ["radio.util.header@1.0"],
- test_suites: ["general-tests", "vts-core"]
+ test_suites: ["general-tests", "vts"]
}
diff --git a/radio/1.5/vts/functional/Android.bp b/radio/1.5/vts/functional/Android.bp
index cd30f7d..cd54d27 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", "vts-core"]
+ test_suites: ["general-tests", "vts"]
}
diff --git a/radio/config/1.0/vts/functional/Android.bp b/radio/config/1.0/vts/functional/Android.bp
index 859b24b..330209e 100644
--- a/radio/config/1.0/vts/functional/Android.bp
+++ b/radio/config/1.0/vts/functional/Android.bp
@@ -29,5 +29,5 @@
"android.hardware.radio.config@1.0",
],
header_libs: ["radio.util.header@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/radio/config/1.1/vts/functional/Android.bp b/radio/config/1.1/vts/functional/Android.bp
index 8cf7b62..f60331d 100644
--- a/radio/config/1.1/vts/functional/Android.bp
+++ b/radio/config/1.1/vts/functional/Android.bp
@@ -29,5 +29,5 @@
"android.hardware.radio.config@1.1",
],
header_libs: ["radio.util.header@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/radio/config/1.2/vts/functional/Android.bp b/radio/config/1.2/vts/functional/Android.bp
index 2c2073a..fdc83b7 100644
--- a/radio/config/1.2/vts/functional/Android.bp
+++ b/radio/config/1.2/vts/functional/Android.bp
@@ -31,5 +31,5 @@
"android.hardware.radio.config@1.2",
],
header_libs: ["radio.util.header@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/rebootescrow/aidl/Android.bp b/rebootescrow/aidl/Android.bp
index 0742939..75faa1a 100644
--- a/rebootescrow/aidl/Android.bp
+++ b/rebootescrow/aidl/Android.bp
@@ -15,4 +15,5 @@
},
},
},
+ versions: ["1"],
}
diff --git a/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/1/.hash b/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/1/.hash
new file mode 100644
index 0000000..dcee3cc
--- /dev/null
+++ b/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/1/.hash
@@ -0,0 +1 @@
+ba450432e0dab8ee7bbc30013819ea8aef12054b
diff --git a/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/1/android/hardware/rebootescrow/IRebootEscrow.aidl b/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/1/android/hardware/rebootescrow/IRebootEscrow.aidl
new file mode 100644
index 0000000..ea669a3
--- /dev/null
+++ b/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/1/android/hardware/rebootescrow/IRebootEscrow.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.rebootescrow;
+@VintfStability
+interface IRebootEscrow {
+ void storeKey(in byte[] kek);
+ byte[] retrieveKey();
+}
diff --git a/rebootescrow/aidl/vts/functional/Android.bp b/rebootescrow/aidl/vts/functional/Android.bp
index 5d51a53..2cc0068 100644
--- a/rebootescrow/aidl/vts/functional/Android.bp
+++ b/rebootescrow/aidl/vts/functional/Android.bp
@@ -28,7 +28,7 @@
"android.hardware.rebootescrow-cpp",
],
test_suites: [
- "vts-core",
+ "vts",
],
require_root: true,
}
diff --git a/renderscript/1.0/vts/functional/Android.bp b/renderscript/1.0/vts/functional/Android.bp
index e3716e0..327c09e 100644
--- a/renderscript/1.0/vts/functional/Android.bp
+++ b/renderscript/1.0/vts/functional/Android.bp
@@ -28,5 +28,5 @@
"android.hardware.renderscript@1.0",
"libnativewindow",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/secure_element/1.0/vts/OWNERS b/secure_element/1.0/vts/OWNERS
new file mode 100644
index 0000000..c7963e7
--- /dev/null
+++ b/secure_element/1.0/vts/OWNERS
@@ -0,0 +1,4 @@
+alisher@google.com
+jackcwyu@google.com
+georgekgchang@google.com
+zachoverflow@google.com
diff --git a/secure_element/1.0/vts/functional/Android.bp b/secure_element/1.0/vts/functional/Android.bp
index 6dbd027..d428c6f 100644
--- a/secure_element/1.0/vts/functional/Android.bp
+++ b/secure_element/1.0/vts/functional/Android.bp
@@ -21,5 +21,5 @@
static_libs: [
"android.hardware.secure_element@1.0",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/secure_element/1.1/vts/OWNERS b/secure_element/1.1/vts/OWNERS
new file mode 100644
index 0000000..c7963e7
--- /dev/null
+++ b/secure_element/1.1/vts/OWNERS
@@ -0,0 +1,4 @@
+alisher@google.com
+jackcwyu@google.com
+georgekgchang@google.com
+zachoverflow@google.com
diff --git a/secure_element/1.1/vts/functional/Android.bp b/secure_element/1.1/vts/functional/Android.bp
index a2c39dc..200aed8 100644
--- a/secure_element/1.1/vts/functional/Android.bp
+++ b/secure_element/1.1/vts/functional/Android.bp
@@ -22,5 +22,5 @@
"android.hardware.secure_element@1.0",
"android.hardware.secure_element@1.1",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/secure_element/1.2/vts/OWNERS b/secure_element/1.2/vts/OWNERS
new file mode 100644
index 0000000..c7963e7
--- /dev/null
+++ b/secure_element/1.2/vts/OWNERS
@@ -0,0 +1,4 @@
+alisher@google.com
+jackcwyu@google.com
+georgekgchang@google.com
+zachoverflow@google.com
diff --git a/secure_element/1.2/vts/functional/Android.bp b/secure_element/1.2/vts/functional/Android.bp
index a173210..9a7ca45 100644
--- a/secure_element/1.2/vts/functional/Android.bp
+++ b/secure_element/1.2/vts/functional/Android.bp
@@ -23,5 +23,5 @@
"android.hardware.secure_element@1.1",
"android.hardware.secure_element@1.2",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp b/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp
index 98e4502..9392f14 100644
--- a/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp
+++ b/secure_element/1.2/vts/functional/VtsHalSecureElementV1_2TargetTest.cpp
@@ -85,6 +85,7 @@
* Reset:
* Calls reset()
* Checks status
+ * Check onStateChange is received with connected state set to false
* Check onStateChange is received with connected state set to true
*/
TEST_P(SecureElementHidlTest, Reset) {
@@ -92,6 +93,10 @@
auto res = se_cb_->WaitForCallback(kCallbackNameOnStateChange);
EXPECT_TRUE(res.no_timeout);
+ EXPECT_FALSE(res.args->state_);
+
+ res = se_cb_->WaitForCallback(kCallbackNameOnStateChange);
+ EXPECT_TRUE(res.no_timeout);
EXPECT_TRUE(res.args->state_);
}
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index aaefccb..31424ab 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -33,6 +33,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 3ce3390..bf51fcd 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -25,6 +25,9 @@
],
init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
+ header_libs: [
+ "android.hardware.sensors@2.X-shared-utils",
+ ],
shared_libs: [
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.0-ScopedWakelock",
@@ -37,5 +40,8 @@
"libpower",
"libutils",
],
- static_libs: ["android.hardware.sensors@2.X-multihal"],
+ static_libs: [
+ "android.hardware.sensors@1.0-convert",
+ "android.hardware.sensors@2.X-multihal",
+ ],
}
diff --git a/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc b/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc
index a4da3b0..0b3d4c2 100644
--- a/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc
+++ b/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc
@@ -1,7 +1,7 @@
service vendor.sensors-hal-2-0-multihal /vendor/bin/hw/android.hardware.sensors@2.0-service.multihal
class hal
user system
- group system wakelock
+ group system wakelock context_hub
writepid /dev/cpuset/system-background/tasks
capabilities BLOCK_SUSPEND
rlimit rtprio 10 10
diff --git a/sensors/2.0/multihal/service.cpp b/sensors/2.0/multihal/service.cpp
index ef77048..f50ad7e 100644
--- a/sensors/2.0/multihal/service.cpp
+++ b/sensors/2.0/multihal/service.cpp
@@ -23,12 +23,12 @@
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::sensors::V2_0::ISensors;
-using android::hardware::sensors::V2_0::implementation::HalProxy;
+using android::hardware::sensors::V2_1::implementation::HalProxyV2_0;
int main(int /* argc */, char** /* argv */) {
configureRpcThreadpool(1, true);
- android::sp<ISensors> halProxy = new HalProxy();
+ android::sp<ISensors> halProxy = new HalProxyV2_0();
if (halProxy->registerAsService() != ::android::OK) {
ALOGE("Failed to register Sensors HAL instance");
return -1;
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index 08c59b6..598ad15 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -40,6 +40,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/sensors/2.1/multihal/Android.bp b/sensors/2.1/multihal/Android.bp
new file mode 100644
index 0000000..6a7cac9
--- /dev/null
+++ b/sensors/2.1/multihal/Android.bp
@@ -0,0 +1,47 @@
+//
+// 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.
+
+cc_binary {
+ name: "android.hardware.sensors@2.1-service.multihal",
+ defaults: [
+ "hidl_defaults",
+ ],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "service.cpp",
+ ],
+ init_rc: ["android.hardware.sensors@2.1-service-multihal.rc"],
+ vintf_fragments: ["android.hardware.sensors@2.1-multihal.xml"],
+ header_libs: [
+ "android.hardware.sensors@2.X-shared-utils",
+ ],
+ shared_libs: [
+ "android.hardware.sensors@2.0",
+ "android.hardware.sensors@2.0-ScopedWakelock",
+ "android.hardware.sensors@2.1",
+ "libbase",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "liblog",
+ "libpower",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.sensors@1.0-convert",
+ "android.hardware.sensors@2.X-multihal",
+ ],
+}
diff --git a/sensors/2.1/multihal/OWNERS b/sensors/2.1/multihal/OWNERS
new file mode 100644
index 0000000..e955670
--- /dev/null
+++ b/sensors/2.1/multihal/OWNERS
@@ -0,0 +1,3 @@
+arthuri@google.com
+bduddie@google.com
+stange@google.com
\ No newline at end of file
diff --git a/sensors/2.1/multihal/android.hardware.sensors@2.1-multihal.xml b/sensors/2.1/multihal/android.hardware.sensors@2.1-multihal.xml
new file mode 100644
index 0000000..18bd3ae
--- /dev/null
+++ b/sensors/2.1/multihal/android.hardware.sensors@2.1-multihal.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.sensors</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <interface>
+ <name>ISensors</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/sensors/2.1/multihal/android.hardware.sensors@2.1-service-multihal.rc b/sensors/2.1/multihal/android.hardware.sensors@2.1-service-multihal.rc
new file mode 100644
index 0000000..fc99ee7
--- /dev/null
+++ b/sensors/2.1/multihal/android.hardware.sensors@2.1-service-multihal.rc
@@ -0,0 +1,7 @@
+service vendor.sensors-hal-2-1-multihal /vendor/bin/hw/android.hardware.sensors@2.1-service.multihal
+ class hal
+ user system
+ group system wakelock context_hub
+ writepid /dev/cpuset/system-background/tasks
+ capabilities BLOCK_SUSPEND
+ rlimit rtprio 10 10
diff --git a/sensors/2.1/multihal/service.cpp b/sensors/2.1/multihal/service.cpp
new file mode 100644
index 0000000..d68d9a3
--- /dev/null
+++ b/sensors/2.1/multihal/service.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 <android/hardware/sensors/2.1/ISensors.h>
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+#include <utils/StrongPointer.h>
+#include "HalProxy.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::sensors::V2_1::ISensors;
+using android::hardware::sensors::V2_1::implementation::HalProxyV2_1;
+
+int main(int /* argc */, char** /* argv */) {
+ configureRpcThreadpool(1, true);
+
+ android::sp<ISensors> halProxy = new HalProxyV2_1();
+ if (halProxy->registerAsService() != ::android::OK) {
+ ALOGE("Failed to register Sensors HAL instance");
+ return -1;
+ }
+
+ joinRpcThreadpool();
+ return 1; // joinRpcThreadpool shouldn't exit
+}
diff --git a/sensors/2.1/vts/functional/Android.bp b/sensors/2.1/vts/functional/Android.bp
index c4f5e9d..3f01a3e 100644
--- a/sensors/2.1/vts/functional/Android.bp
+++ b/sensors/2.1/vts/functional/Android.bp
@@ -42,6 +42,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/sensors/common/default/2.X/multihal/Android.bp b/sensors/common/default/2.X/multihal/Android.bp
index 6122323..c80c47a 100644
--- a/sensors/common/default/2.X/multihal/Android.bp
+++ b/sensors/common/default/2.X/multihal/Android.bp
@@ -17,6 +17,7 @@
name: "android.hardware.sensors@2.X-multihal-defaults",
header_libs: [
"android.hardware.sensors@2.X-multihal.header",
+ "android.hardware.sensors@2.X-shared-utils",
],
shared_libs: [
"android.hardware.sensors@1.0",
@@ -30,6 +31,9 @@
"libpower",
"libutils",
],
+ static_libs: [
+ "android.hardware.sensors@1.0-convert",
+ ],
cflags: ["-DLOG_TAG=\"SensorsMultiHal\""],
}
@@ -62,6 +66,7 @@
],
srcs: [
"HalProxy.cpp",
+ "HalProxyCallback.cpp",
],
vendor_available: true,
export_header_lib_headers: [
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index 518e138..a09e9e9 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -32,15 +32,17 @@
namespace android {
namespace hardware {
namespace sensors {
-namespace V2_0 {
+namespace V2_1 {
namespace implementation {
+using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
using ::android::hardware::sensors::V2_0::implementation::getTimeNow;
using ::android::hardware::sensors::V2_0::implementation::kWakelockTimeoutNs;
-typedef ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*);
+typedef V2_0::implementation::ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*);
+typedef V2_1::implementation::ISensorsSubHal*(SensorsHalGetSubHalV2_1Func)(uint32_t*);
static constexpr int32_t kBitsAfterSubHalIndex = 24;
@@ -85,7 +87,24 @@
init();
}
-HalProxy::HalProxy(std::vector<ISensorsSubHal*>& subHalList) : mSubHalList(subHalList) {
+HalProxy::HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList) {
+ for (ISensorsSubHalV2_0* subHal : subHalList) {
+ mSubHalList.push_back(std::make_unique<SubHalWrapperV2_0>(subHal));
+ }
+
+ init();
+}
+
+HalProxy::HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList,
+ std::vector<ISensorsSubHalV2_1*>& subHalListV2_1) {
+ for (ISensorsSubHalV2_0* subHal : subHalList) {
+ mSubHalList.push_back(std::make_unique<SubHalWrapperV2_0>(subHal));
+ }
+
+ for (ISensorsSubHalV2_1* subHal : subHalListV2_1) {
+ mSubHalList.push_back(std::make_unique<SubHalWrapperV2_1>(subHal));
+ }
+
init();
}
@@ -93,8 +112,8 @@
stopThreads();
}
-Return<void> HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) {
- std::vector<SensorInfo> sensors;
+Return<void> HalProxy::getSensorsList_2_1(ISensorsV2_1::getSensorsList_2_1_cb _hidl_cb) {
+ std::vector<V2_1::SensorInfo> sensors;
for (const auto& iter : mSensors) {
sensors.push_back(iter.second);
}
@@ -102,22 +121,31 @@
return Void();
}
+Return<void> HalProxy::getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb) {
+ std::vector<V1_0::SensorInfo> sensors;
+ for (const auto& iter : mSensors) {
+ sensors.push_back(convertToOldSensorInfo(iter.second));
+ }
+ _hidl_cb(sensors);
+ return Void();
+}
+
Return<Result> HalProxy::setOperationMode(OperationMode mode) {
Result result = Result::OK;
size_t subHalIndex;
for (subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
- ISensorsSubHal* subHal = mSubHalList[subHalIndex];
- result = subHal->setOperationMode(mode);
+ result = mSubHalList[subHalIndex]->setOperationMode(mode);
if (result != Result::OK) {
- ALOGE("setOperationMode failed for SubHal: %s", subHal->getName().c_str());
+ ALOGE("setOperationMode failed for SubHal: %s",
+ mSubHalList[subHalIndex]->getName().c_str());
break;
}
}
+
if (result != Result::OK) {
// Reset the subhal operation modes that have been flipped
for (size_t i = 0; i < subHalIndex; i++) {
- ISensorsSubHal* subHal = mSubHalList[i];
- subHal->setOperationMode(mCurrentOperationMode);
+ mSubHalList[i]->setOperationMode(mCurrentOperationMode);
}
} else {
mCurrentOperationMode = mode;
@@ -133,10 +161,42 @@
->activate(clearSubHalIndex(sensorHandle), enabled);
}
-Return<Result> HalProxy::initialize(
- const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
+Return<Result> HalProxy::initialize_2_1(
+ const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
- const sp<ISensorsCallback>& sensorsCallback) {
+ const sp<V2_1::ISensorsCallback>& sensorsCallback) {
+ sp<ISensorsCallbackWrapperBase> dynamicCallback =
+ new ISensorsCallbackWrapperV2_1(sensorsCallback);
+
+ // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
+ auto eventQueue =
+ std::make_unique<EventMessageQueueV2_1>(eventQueueDescriptor, true /* resetPointers */);
+ std::unique_ptr<EventMessageQueueWrapperBase> queue =
+ std::make_unique<EventMessageQueueWrapperV2_1>(eventQueue);
+
+ return initializeCommon(queue, wakeLockDescriptor, dynamicCallback);
+}
+
+Return<Result> HalProxy::initialize(
+ const ::android::hardware::MQDescriptorSync<V1_0::Event>& eventQueueDescriptor,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<V2_0::ISensorsCallback>& sensorsCallback) {
+ sp<ISensorsCallbackWrapperBase> dynamicCallback =
+ new ISensorsCallbackWrapperV2_0(sensorsCallback);
+
+ // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
+ auto eventQueue =
+ std::make_unique<EventMessageQueueV2_0>(eventQueueDescriptor, true /* resetPointers */);
+ std::unique_ptr<EventMessageQueueWrapperBase> queue =
+ std::make_unique<EventMessageQueueWrapperV1_0>(eventQueue);
+
+ return initializeCommon(queue, wakeLockDescriptor, dynamicCallback);
+}
+
+Return<Result> HalProxy::initializeCommon(
+ std::unique_ptr<EventMessageQueueWrapperBase>& eventQueue,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<ISensorsCallbackWrapperBase>& sensorsCallback) {
Result result = Result::OK;
stopThreads();
@@ -147,7 +207,7 @@
disableAllSensors();
// Clears the queue if any events were pending write before.
- mPendingWriteEventsQueue = std::queue<std::pair<std::vector<Event>, size_t>>();
+ mPendingWriteEventsQueue = std::queue<std::pair<std::vector<V2_1::Event>, size_t>>();
mSizePendingWriteEventsQueue = 0;
// Clears previously connected dynamic sensors
@@ -156,8 +216,7 @@
mDynamicSensorsCallback = sensorsCallback;
// Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
- mEventQueue =
- std::make_unique<EventMessageQueue>(eventQueueDescriptor, true /* resetPointers */);
+ mEventQueue = std::move(eventQueue);
// Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP
// events have been successfully read and handled by the framework.
@@ -186,12 +245,10 @@
mWakelockThread = std::thread(startWakelockThread, this);
for (size_t i = 0; i < mSubHalList.size(); i++) {
- auto subHal = mSubHalList[i];
- const auto& subHalCallback = mSubHalCallbacks[i];
- Result currRes = subHal->initialize(subHalCallback);
+ Result currRes = mSubHalList[i]->initialize(this, this, i);
if (currRes != Result::OK) {
result = currRes;
- ALOGE("Subhal '%s' failed to initialize.", subHal->getName().c_str());
+ ALOGE("Subhal '%s' failed to initialize.", mSubHalList[i]->getName().c_str());
break;
}
}
@@ -217,7 +274,11 @@
return getSubHalForSensorHandle(sensorHandle)->flush(clearSubHalIndex(sensorHandle));
}
-Return<Result> HalProxy::injectSensorData(const Event& event) {
+Return<Result> HalProxy::injectSensorData_2_1(const V2_1::Event& event) {
+ return injectSensorData(convertToOldEvent(event));
+}
+
+Return<Result> HalProxy::injectSensorData(const V1_0::Event& event) {
Result result = Result::OK;
if (mCurrentOperationMode == OperationMode::NORMAL &&
event.sensorType != V1_0::SensorType::ADDITIONAL_INFO) {
@@ -226,18 +287,19 @@
result = Result::BAD_VALUE;
}
if (result == Result::OK) {
- Event subHalEvent = event;
+ V1_0::Event subHalEvent = event;
if (!isSubHalIndexValid(event.sensorHandle)) {
return Result::BAD_VALUE;
}
subHalEvent.sensorHandle = clearSubHalIndex(event.sensorHandle);
- result = getSubHalForSensorHandle(event.sensorHandle)->injectSensorData(subHalEvent);
+ result = getSubHalForSensorHandle(event.sensorHandle)
+ ->injectSensorData(convertToNewEvent(subHalEvent));
}
return result;
}
Return<void> HalProxy::registerDirectChannel(const SharedMemInfo& mem,
- registerDirectChannel_cb _hidl_cb) {
+ ISensorsV2_0::registerDirectChannel_cb _hidl_cb) {
if (mDirectChannelSubHal == nullptr) {
_hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
} else {
@@ -257,12 +319,18 @@
}
Return<void> HalProxy::configDirectReport(int32_t sensorHandle, int32_t channelHandle,
- RateLevel rate, configDirectReport_cb _hidl_cb) {
+ RateLevel rate,
+ ISensorsV2_0::configDirectReport_cb _hidl_cb) {
if (mDirectChannelSubHal == nullptr) {
_hidl_cb(Result::INVALID_OPERATION, -1 /* reportToken */);
+ } else if (sensorHandle == -1 && rate != RateLevel::STOP) {
+ _hidl_cb(Result::BAD_VALUE, -1 /* reportToken */);
} else {
- mDirectChannelSubHal->configDirectReport(clearSubHalIndex(sensorHandle), channelHandle,
- rate, _hidl_cb);
+ // -1 denotes all sensors should be disabled
+ if (sensorHandle != -1) {
+ sensorHandle = clearSubHalIndex(sensorHandle);
+ }
+ mDirectChannelSubHal->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
}
return Return<void>();
}
@@ -297,7 +365,7 @@
stream << " # of non-dynamic sensors across all subhals: " << mSensors.size() << std::endl;
stream << " # of dynamic sensors across all subhals: " << mDynamicSensors.size() << std::endl;
stream << "SubHals (" << mSubHalList.size() << "):" << std::endl;
- for (ISensorsSubHal* subHal : mSubHalList) {
+ for (auto& subHal : mSubHalList) {
stream << " Name: " << subHal->getName() << std::endl;
stream << " Debug dump: " << std::endl;
android::base::WriteStringToFd(stream.str(), writeFd);
@@ -364,20 +432,37 @@
} else {
SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr =
(SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal");
- if (sensorsHalGetSubHalPtr == nullptr) {
- ALOGE("Failed to locate sensorsHalGetSubHal function for library: %s",
- subHalLibraryFile.c_str());
- } else {
+ if (sensorsHalGetSubHalPtr != nullptr) {
std::function<SensorsHalGetSubHalFunc> sensorsHalGetSubHal =
*sensorsHalGetSubHalPtr;
uint32_t version;
- ISensorsSubHal* subHal = sensorsHalGetSubHal(&version);
+ ISensorsSubHalV2_0* subHal = sensorsHalGetSubHal(&version);
if (version != SUB_HAL_2_0_VERSION) {
ALOGE("SubHal version was not 2.0 for library: %s",
subHalLibraryFile.c_str());
} else {
ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
- mSubHalList.push_back(subHal);
+ mSubHalList.push_back(std::make_unique<SubHalWrapperV2_0>(subHal));
+ }
+ } else {
+ SensorsHalGetSubHalV2_1Func* getSubHalV2_1Ptr =
+ (SensorsHalGetSubHalV2_1Func*)dlsym(handle, "sensorsHalGetSubHal_2_1");
+
+ if (getSubHalV2_1Ptr == nullptr) {
+ ALOGE("Failed to locate sensorsHalGetSubHal function for library: %s",
+ subHalLibraryFile.c_str());
+ } else {
+ std::function<SensorsHalGetSubHalV2_1Func> sensorsHalGetSubHal_2_1 =
+ *getSubHalV2_1Ptr;
+ uint32_t version;
+ ISensorsSubHalV2_1* subHal = sensorsHalGetSubHal_2_1(&version);
+ if (version != SUB_HAL_2_1_VERSION) {
+ ALOGE("SubHal version was not 2.1 for library: %s",
+ subHalLibraryFile.c_str());
+ } else {
+ ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
+ mSubHalList.push_back(std::make_unique<SubHalWrapperV2_1>(subHal));
+ }
}
}
}
@@ -385,36 +470,28 @@
}
}
-void HalProxy::initializeSubHalCallbacks() {
- for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
- sp<IHalProxyCallback> callback = new HalProxyCallback(this, subHalIndex);
- mSubHalCallbacks.push_back(callback);
- }
-}
-
void HalProxy::initializeSensorList() {
for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
- ISensorsSubHal* subHal = mSubHalList[subHalIndex];
- auto result = subHal->getSensorsList([&](const auto& list) {
+ auto result = mSubHalList[subHalIndex]->getSensorsList([&](const auto& list) {
for (SensorInfo sensor : list) {
if (!subHalIndexIsClear(sensor.sensorHandle)) {
ALOGE("SubHal sensorHandle's first byte was not 0");
} else {
ALOGV("Loaded sensor: %s", sensor.name.c_str());
sensor.sensorHandle = setSubHalIndex(sensor.sensorHandle, subHalIndex);
- setDirectChannelFlags(&sensor, subHal);
+ setDirectChannelFlags(&sensor, mSubHalList[subHalIndex]);
mSensors[sensor.sensorHandle] = sensor;
}
}
});
if (!result.isOk()) {
- ALOGE("getSensorsList call failed for SubHal: %s", subHal->getName().c_str());
+ ALOGE("getSensorsList call failed for SubHal: %s",
+ mSubHalList[subHalIndex]->getName().c_str());
}
}
}
void HalProxy::init() {
- initializeSubHalCallbacks();
initializeSensorList();
}
@@ -547,7 +624,7 @@
}
void HalProxy::postEventsToMessageQueue(const std::vector<Event>& events, size_t numWakeupEvents,
- ScopedWakelock wakelock) {
+ V2_0::implementation::ScopedWakelock wakelock) {
size_t numToWrite = 0;
std::lock_guard<std::mutex> lock(mEventQueueWriteMutex);
if (wakelock.isLocked()) {
@@ -605,7 +682,8 @@
}
}
-void HalProxy::setDirectChannelFlags(SensorInfo* sensorInfo, ISensorsSubHal* subHal) {
+void HalProxy::setDirectChannelFlags(SensorInfo* sensorInfo,
+ std::shared_ptr<ISubHalWrapperBase> subHal) {
bool sensorSupportsDirectChannel =
(sensorInfo->flags & (V1_0::SensorFlagBits::MASK_DIRECT_REPORT |
V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL)) != 0;
@@ -619,7 +697,7 @@
}
}
-ISensorsSubHal* HalProxy::getSubHalForSensorHandle(int32_t sensorHandle) {
+std::shared_ptr<ISubHalWrapperBase> HalProxy::getSubHalForSensorHandle(int32_t sensorHandle) {
return mSubHalList[extractSubHalIndex(sensorHandle)];
}
@@ -646,46 +724,8 @@
return (sensorHandle & kSensorHandleSubHalIndexMask) == 0;
}
-void HalProxyCallback::postEvents(const std::vector<Event>& events, ScopedWakelock wakelock) {
- if (events.empty() || !mHalProxy->areThreadsRunning()) return;
- size_t numWakeupEvents;
- std::vector<Event> processedEvents = processEvents(events, &numWakeupEvents);
- if (numWakeupEvents > 0) {
- ALOG_ASSERT(wakelock.isLocked(),
- "Wakeup events posted while wakelock unlocked for subhal"
- " w/ index %" PRId32 ".",
- mSubHalIndex);
- } else {
- ALOG_ASSERT(!wakelock.isLocked(),
- "No Wakeup events posted but wakelock locked for subhal"
- " w/ index %" PRId32 ".",
- mSubHalIndex);
- }
- mHalProxy->postEventsToMessageQueue(processedEvents, numWakeupEvents, std::move(wakelock));
-}
-
-ScopedWakelock HalProxyCallback::createScopedWakelock(bool lock) {
- ScopedWakelock wakelock(mHalProxy, lock);
- return wakelock;
-}
-
-std::vector<Event> HalProxyCallback::processEvents(const std::vector<Event>& events,
- size_t* numWakeupEvents) const {
- *numWakeupEvents = 0;
- std::vector<Event> eventsOut;
- for (Event event : events) {
- event.sensorHandle = setSubHalIndex(event.sensorHandle, mSubHalIndex);
- eventsOut.push_back(event);
- const SensorInfo& sensor = mHalProxy->getSensorInfo(event.sensorHandle);
- if ((sensor.flags & V1_0::SensorFlagBits::WAKE_UP) != 0) {
- (*numWakeupEvents)++;
- }
- }
- return eventsOut;
-}
-
} // namespace implementation
-} // namespace V2_0
+} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
diff --git a/sensors/common/default/2.X/multihal/HalProxyCallback.cpp b/sensors/common/default/2.X/multihal/HalProxyCallback.cpp
new file mode 100644
index 0000000..3c1b17c
--- /dev/null
+++ b/sensors/common/default/2.X/multihal/HalProxyCallback.cpp
@@ -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.
+ */
+
+#include "HalProxyCallback.h"
+
+#include <cinttypes>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+static constexpr int32_t kBitsAfterSubHalIndex = 24;
+
+/**
+ * Set the subhal index as first byte of sensor handle and return this modified version.
+ *
+ * @param sensorHandle The sensor handle to modify.
+ * @param subHalIndex The index in the hal proxy of the sub hal this sensor belongs to.
+ *
+ * @return The modified sensor handle.
+ */
+int32_t setSubHalIndex(int32_t sensorHandle, size_t subHalIndex) {
+ return sensorHandle | (static_cast<int32_t>(subHalIndex) << kBitsAfterSubHalIndex);
+}
+
+void HalProxyCallbackBase::postEvents(const std::vector<V2_1::Event>& events,
+ ScopedWakelock wakelock) {
+ if (events.empty() || !mCallback->areThreadsRunning()) return;
+ size_t numWakeupEvents;
+ std::vector<V2_1::Event> processedEvents = processEvents(events, &numWakeupEvents);
+ if (numWakeupEvents > 0) {
+ ALOG_ASSERT(wakelock.isLocked(),
+ "Wakeup events posted while wakelock unlocked for subhal"
+ " w/ index %" PRId32 ".",
+ mSubHalIndex);
+ } else {
+ ALOG_ASSERT(!wakelock.isLocked(),
+ "No Wakeup events posted but wakelock locked for subhal"
+ " w/ index %" PRId32 ".",
+ mSubHalIndex);
+ }
+ mCallback->postEventsToMessageQueue(processedEvents, numWakeupEvents, std::move(wakelock));
+}
+
+ScopedWakelock HalProxyCallbackBase::createScopedWakelock(bool lock) {
+ ScopedWakelock wakelock(mRefCounter, lock);
+ return wakelock;
+}
+
+std::vector<V2_1::Event> HalProxyCallbackBase::processEvents(const std::vector<V2_1::Event>& events,
+ size_t* numWakeupEvents) const {
+ *numWakeupEvents = 0;
+ std::vector<V2_1::Event> eventsOut;
+ for (V2_1::Event event : events) {
+ event.sensorHandle = setSubHalIndex(event.sensorHandle, mSubHalIndex);
+ eventsOut.push_back(event);
+ const V2_1::SensorInfo& sensor = mCallback->getSensorInfo(event.sensorHandle);
+ if ((sensor.flags & V1_0::SensorFlagBits::WAKE_UP) != 0) {
+ (*numWakeupEvents)++;
+ }
+ }
+ return eventsOut;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace sensors
+} // namespace hardware
+} // namespace android
diff --git a/sensors/common/default/2.X/multihal/include/HalProxy.h b/sensors/common/default/2.X/multihal/include/HalProxy.h
index d7e8795..fb0b806 100644
--- a/sensors/common/default/2.X/multihal/include/HalProxy.h
+++ b/sensors/common/default/2.X/multihal/include/HalProxy.h
@@ -16,12 +16,17 @@
#pragma once
+#include "EventMessageQueueWrapper.h"
+#include "HalProxyCallback.h"
+#include "ISensorsCallbackWrapper.h"
+#include "SubHalWrapper.h"
#include "V2_0/ScopedWakelock.h"
#include "V2_0/SubHal.h"
#include "V2_1/SubHal.h"
+#include "convertV2_1.h"
-#include <android/hardware/sensors/2.0/ISensors.h>
-#include <android/hardware/sensors/2.0/types.h>
+#include <android/hardware/sensors/2.1/ISensors.h>
+#include <android/hardware/sensors/2.1/types.h>
#include <fmq/MessageQueue.h>
#include <hardware_legacy/power.h>
#include <hidl/MQDescriptor.h>
@@ -38,96 +43,97 @@
namespace android {
namespace hardware {
namespace sensors {
-namespace V2_0 {
+namespace V2_1 {
namespace implementation {
-using ::android::sp;
-using ::android::hardware::EventFlag;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::MQDescriptor;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-class HalProxy : public ISensors, public IScopedWakelockRefCounter {
+/**
+ * HalProxy is the main interface for Multi-HAL. It is responsible for managing subHALs and
+ * proxying function calls to/from the subHAL APIs from the sensors framework. It also manages any
+ * wakelocks allocated through the IHalProxyCallback and manages posting events to the sensors
+ * framework.
+ */
+class HalProxy : public V2_0::implementation::IScopedWakelockRefCounter,
+ public V2_0::implementation::ISubHalCallback {
public:
- using Event = ::android::hardware::sensors::V1_0::Event;
+ using Event = ::android::hardware::sensors::V2_1::Event;
using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
using Result = ::android::hardware::sensors::V1_0::Result;
- using SensorInfo = ::android::hardware::sensors::V1_0::SensorInfo;
+ using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
- using ISensorsSubHal = ::android::hardware::sensors::V2_0::implementation::ISensorsSubHal;
+ using IHalProxyCallbackV2_0 = V2_0::implementation::IHalProxyCallback;
+ using IHalProxyCallbackV2_1 = V2_1::implementation::IHalProxyCallback;
+ using ISensorsSubHalV2_0 = V2_0::implementation::ISensorsSubHal;
+ using ISensorsSubHalV2_1 = V2_1::implementation::ISensorsSubHal;
+ using ISensorsV2_0 = V2_0::ISensors;
+ using ISensorsV2_1 = V2_1::ISensors;
+ using HalProxyCallbackBase = V2_0::implementation::HalProxyCallbackBase;
explicit HalProxy();
// Test only constructor.
- explicit HalProxy(std::vector<ISensorsSubHal*>& subHalList);
+ explicit HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList);
+ explicit HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList,
+ std::vector<ISensorsSubHalV2_1*>& subHalListV2_1);
~HalProxy();
+ // Methods from ::android::hardware::sensors::V2_1::ISensors follow.
+ Return<void> getSensorsList_2_1(ISensorsV2_1::getSensorsList_2_1_cb _hidl_cb);
+
+ Return<Result> initialize_2_1(
+ const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<V2_1::ISensorsCallback>& sensorsCallback);
+
+ Return<Result> injectSensorData_2_1(const Event& event);
+
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
- Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+ Return<void> getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb);
- Return<Result> setOperationMode(OperationMode mode) override;
+ Return<Result> setOperationMode(OperationMode mode);
- Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+ Return<Result> activate(int32_t sensorHandle, bool enabled);
Return<Result> initialize(
- const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
+ const ::android::hardware::MQDescriptorSync<V1_0::Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
- const sp<ISensorsCallback>& sensorsCallback) override;
+ const sp<V2_0::ISensorsCallback>& sensorsCallback);
+
+ Return<Result> initializeCommon(
+ std::unique_ptr<EventMessageQueueWrapperBase>& eventQueue,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<ISensorsCallbackWrapperBase>& sensorsCallback);
Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
- int64_t maxReportLatencyNs) override;
+ int64_t maxReportLatencyNs);
- Return<Result> flush(int32_t sensorHandle) override;
+ Return<Result> flush(int32_t sensorHandle);
- Return<Result> injectSensorData(const Event& event) override;
+ Return<Result> injectSensorData(const V1_0::Event& event);
Return<void> registerDirectChannel(const SharedMemInfo& mem,
- registerDirectChannel_cb _hidl_cb) override;
+ ISensorsV2_0::registerDirectChannel_cb _hidl_cb);
- Return<Result> unregisterDirectChannel(int32_t channelHandle) override;
+ Return<Result> unregisterDirectChannel(int32_t channelHandle);
Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
- configDirectReport_cb _hidl_cb) override;
+ ISensorsV2_0::configDirectReport_cb _hidl_cb);
- Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args);
- // Below methods from ::android::hardware::sensors::V2_0::ISensorsCallback with a minor change
- // to pass in the sub-HAL index. While the above methods are invoked from the sensors framework
- // via the binder, these methods are invoked from a callback provided to sub-HALs inside the
- // same process as the HalProxy, but potentially running on different threads.
Return<void> onDynamicSensorsConnected(const hidl_vec<SensorInfo>& dynamicSensorsAdded,
- int32_t subHalIndex);
+ int32_t subHalIndex) override;
Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& dynamicSensorHandlesRemoved,
- int32_t subHalIndex);
+ int32_t subHalIndex) override;
- // Below methods are for HalProxyCallback
-
- /**
- * Post events to the event message queue if there is room to write them. Otherwise post the
- * remaining events to a background thread for a blocking write with a kPendingWriteTimeoutNs
- * timeout.
- *
- * @param events The list of events to post to the message queue.
- * @param numWakeupEvents The number of wakeup events in events.
- * @param wakelock The wakelock associated with this post of events.
- */
void postEventsToMessageQueue(const std::vector<Event>& events, size_t numWakeupEvents,
- ScopedWakelock wakelock);
+ V2_0::implementation::ScopedWakelock wakelock) override;
- /**
- * Get the sensor info associated with that sensorHandle.
- *
- * @param sensorHandle The sensor handle.
- *
- * @return The sensor info object in the mapping.
- */
- const SensorInfo& getSensorInfo(int32_t sensorHandle) { return mSensors[sensorHandle]; }
+ const SensorInfo& getSensorInfo(int32_t sensorHandle) override {
+ return mSensors[sensorHandle];
+ }
- bool areThreadsRunning() { return mThreadsRun.load(); }
+ bool areThreadsRunning() override { return mThreadsRun.load(); }
// Below methods are from IScopedWakelockRefCounter interface
bool incrementRefCountAndMaybeAcquireWakelock(size_t delta,
@@ -136,13 +142,14 @@
void decrementRefCountAndMaybeReleaseWakelock(size_t delta, int64_t timeoutStart = -1) override;
private:
- using EventMessageQueue = MessageQueue<Event, kSynchronizedReadWrite>;
+ using EventMessageQueueV2_1 = MessageQueue<V2_1::Event, kSynchronizedReadWrite>;
+ using EventMessageQueueV2_0 = MessageQueue<V1_0::Event, kSynchronizedReadWrite>;
using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;
/**
* The Event FMQ where sensor events are written
*/
- std::unique_ptr<EventMessageQueue> mEventQueue;
+ std::unique_ptr<EventMessageQueueWrapperBase> mEventQueue;
/**
* The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
@@ -161,15 +168,12 @@
/**
* Callback to the sensors framework to inform it that new sensors have been added or removed.
*/
- sp<ISensorsCallback> mDynamicSensorsCallback;
+ sp<ISensorsCallbackWrapperBase> mDynamicSensorsCallback;
/**
- * SubHal object pointers that have been saved from vendor dynamic libraries.
+ * SubHal objects that have been saved from vendor dynamic libraries.
*/
- std::vector<ISensorsSubHal*> mSubHalList;
-
- //! The list of subhal callbacks for each subhal where the indices correlate with mSubHalList
- std::vector<const sp<IHalProxyCallback>> mSubHalCallbacks;
+ std::vector<std::shared_ptr<ISubHalWrapperBase>> mSubHalList;
/**
* Map of sensor handles to SensorInfo objects that contains the sensor info from subhals as
@@ -187,7 +191,7 @@
OperationMode mCurrentOperationMode = OperationMode::NORMAL;
//! The single subHal that supports directChannel reporting.
- ISensorsSubHal* mDirectChannelSubHal = nullptr;
+ std::shared_ptr<ISubHalWrapperBase> mDirectChannelSubHal;
//! The timeout for each pending write on background thread for events.
static const int64_t kPendingWriteTimeoutNs = 5 * INT64_C(1000000000) /* 5 seconds */;
@@ -239,9 +243,9 @@
//! The refcount of how many ScopedWakelocks and pending wakeup events are active
size_t mWakelockRefCount = 0;
- int64_t mWakelockTimeoutStartTime = getTimeNow();
+ int64_t mWakelockTimeoutStartTime = V2_0::implementation::getTimeNow();
- int64_t mWakelockTimeoutResetTime = getTimeNow();
+ int64_t mWakelockTimeoutResetTime = V2_0::implementation::getTimeNow();
const char* kWakelockName = "SensorsHAL_WAKEUP";
@@ -321,7 +325,7 @@
* disabled.
* @param subHal The subhal pointer that the current sensorInfo object came from.
*/
- void setDirectChannelFlags(SensorInfo* sensorInfo, ISensorsSubHal* subHal);
+ void setDirectChannelFlags(SensorInfo* sensorInfo, std::shared_ptr<ISubHalWrapperBase> subHal);
/*
* Get the subhal pointer which can be found by indexing into the mSubHalList vector
@@ -329,7 +333,7 @@
*
* @param sensorHandle The handle used to identify a sensor in one of the subhals.
*/
- ISensorsSubHal* getSubHalForSensorHandle(int32_t sensorHandle);
+ std::shared_ptr<ISubHalWrapperBase> getSubHalForSensorHandle(int32_t sensorHandle);
/**
* Checks that sensorHandle's subhal index byte is within bounds of mSubHalList.
@@ -368,39 +372,81 @@
};
/**
- * Callback class used to provide the HalProxy with the index of which subHal is invoking
+ * Since a newer HAL can't masquerade as a older HAL, IHalProxy enables the HalProxy to be compiled
+ * either for HAL 2.0 or HAL 2.1 depending on the build configuration.
*/
-class HalProxyCallback : public IHalProxyCallback {
- using SensorInfo = ::android::hardware::sensors::V1_0::SensorInfo;
-
- public:
- HalProxyCallback(HalProxy* halProxy, int32_t subHalIndex)
- : mHalProxy(halProxy), mSubHalIndex(subHalIndex) {}
-
- Return<void> onDynamicSensorsConnected(
- const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
- return mHalProxy->onDynamicSensorsConnected(dynamicSensorsAdded, mSubHalIndex);
+template <class ISensorsVersion>
+class IHalProxy : public HalProxy, public ISensorsVersion {
+ Return<void> getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb) override {
+ return HalProxy::getSensorsList(_hidl_cb);
}
- Return<void> onDynamicSensorsDisconnected(
- const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
- return mHalProxy->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved, mSubHalIndex);
+ Return<Result> setOperationMode(OperationMode mode) override {
+ return HalProxy::setOperationMode(mode);
}
- void postEvents(const std::vector<Event>& events, ScopedWakelock wakelock);
+ Return<Result> activate(int32_t sensorHandle, bool enabled) override {
+ return HalProxy::activate(sensorHandle, enabled);
+ }
- ScopedWakelock createScopedWakelock(bool lock);
+ Return<Result> initialize(
+ const ::android::hardware::MQDescriptorSync<V1_0::Event>& eventQueueDescriptor,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<V2_0::ISensorsCallback>& sensorsCallback) override {
+ return HalProxy::initialize(eventQueueDescriptor, wakeLockDescriptor, sensorsCallback);
+ }
- private:
- HalProxy* mHalProxy;
- int32_t mSubHalIndex;
+ Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) override {
+ return HalProxy::batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+ }
- std::vector<Event> processEvents(const std::vector<Event>& events,
- size_t* numWakeupEvents) const;
+ Return<Result> flush(int32_t sensorHandle) override { return HalProxy::flush(sensorHandle); }
+
+ Return<Result> injectSensorData(const V1_0::Event& event) override {
+ return HalProxy::injectSensorData(event);
+ }
+
+ Return<void> registerDirectChannel(const SharedMemInfo& mem,
+ ISensorsV2_0::registerDirectChannel_cb _hidl_cb) override {
+ return HalProxy::registerDirectChannel(mem, _hidl_cb);
+ }
+
+ Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+ return HalProxy::unregisterDirectChannel(channelHandle);
+ }
+
+ Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+ ISensorsV2_0::configDirectReport_cb _hidl_cb) override {
+ return HalProxy::configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+ }
+
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override {
+ return HalProxy::debug(fd, args);
+ }
+};
+
+class HalProxyV2_0 : public IHalProxy<V2_0::ISensors> {};
+
+class HalProxyV2_1 : public IHalProxy<V2_1::ISensors> {
+ Return<void> getSensorsList_2_1(ISensorsV2_1::getSensorsList_2_1_cb _hidl_cb) override {
+ return HalProxy::getSensorsList_2_1(_hidl_cb);
+ }
+
+ Return<Result> initialize_2_1(
+ const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<V2_1::ISensorsCallback>& sensorsCallback) override {
+ return HalProxy::initialize_2_1(eventQueueDescriptor, wakeLockDescriptor, sensorsCallback);
+ }
+
+ Return<Result> injectSensorData_2_1(const Event& event) override {
+ return HalProxy::injectSensorData_2_1(event);
+ }
};
} // namespace implementation
-} // namespace V2_0
+} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
diff --git a/sensors/common/default/2.X/multihal/include/HalProxyCallback.h b/sensors/common/default/2.X/multihal/include/HalProxyCallback.h
new file mode 100644
index 0000000..e62b7d1
--- /dev/null
+++ b/sensors/common/default/2.X/multihal/include/HalProxyCallback.h
@@ -0,0 +1,171 @@
+/*
+ * 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 "V2_0/ScopedWakelock.h"
+#include "V2_0/SubHal.h"
+#include "V2_1/SubHal.h"
+#include "convertV2_1.h"
+
+#include <android/hardware/sensors/2.1/ISensors.h>
+#include <android/hardware/sensors/2.1/types.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+/**
+ * Interface used to communicate with the HalProxy when subHals interact with their provided
+ * callback.
+ */
+class ISubHalCallback {
+ public:
+ virtual ~ISubHalCallback() {}
+
+ // Below methods from ::android::hardware::sensors::V2_0::ISensorsCallback with a minor change
+ // to pass in the sub-HAL index. While the above methods are invoked from the sensors framework
+ // via the binder, these methods are invoked from a callback provided to sub-HALs inside the
+ // same process as the HalProxy, but potentially running on different threads.
+ virtual Return<void> onDynamicSensorsConnected(
+ const hidl_vec<V2_1::SensorInfo>& dynamicSensorsAdded, int32_t subHalIndex) = 0;
+
+ virtual Return<void> onDynamicSensorsDisconnected(
+ const hidl_vec<int32_t>& dynamicSensorHandlesRemoved, int32_t subHalIndex) = 0;
+
+ /**
+ * Post events to the event message queue if there is room to write them. Otherwise post the
+ * remaining events to a background thread for a blocking write with a kPendingWriteTimeoutNs
+ * timeout.
+ *
+ * @param events The list of events to post to the message queue.
+ * @param numWakeupEvents The number of wakeup events in events.
+ * @param wakelock The wakelock associated with this post of events.
+ */
+ virtual void postEventsToMessageQueue(const std::vector<V2_1::Event>& events,
+ size_t numWakeupEvents,
+ V2_0::implementation::ScopedWakelock wakelock) = 0;
+
+ /**
+ * Get the sensor info associated with that sensorHandle.
+ *
+ * @param sensorHandle The sensor handle.
+ *
+ * @return The sensor info object in the mapping.
+ */
+ virtual const V2_1::SensorInfo& getSensorInfo(int32_t sensorHandle) = 0;
+
+ virtual bool areThreadsRunning() = 0;
+};
+
+/**
+ * Callback class given to subhals that allows the HalProxy to know which subhal a given invocation
+ * is coming from.
+ */
+class HalProxyCallbackBase : public VirtualLightRefBase {
+ public:
+ HalProxyCallbackBase(ISubHalCallback* callback,
+ V2_0::implementation::IScopedWakelockRefCounter* refCounter,
+ int32_t subHalIndex)
+ : mCallback(callback), mRefCounter(refCounter), mSubHalIndex(subHalIndex) {}
+
+ void postEvents(const std::vector<V2_1::Event>& events,
+ V2_0::implementation::ScopedWakelock wakelock);
+
+ V2_0::implementation::ScopedWakelock createScopedWakelock(bool lock);
+
+ protected:
+ ISubHalCallback* mCallback;
+ V2_0::implementation::IScopedWakelockRefCounter* mRefCounter;
+ int32_t mSubHalIndex;
+
+ private:
+ std::vector<V2_1::Event> processEvents(const std::vector<V2_1::Event>& events,
+ size_t* numWakeupEvents) const;
+};
+
+class HalProxyCallbackV2_0 : public HalProxyCallbackBase,
+ public V2_0::implementation::IHalProxyCallback {
+ public:
+ HalProxyCallbackV2_0(ISubHalCallback* callback,
+ V2_0::implementation::IScopedWakelockRefCounter* refCounter,
+ int32_t subHalIndex)
+ : HalProxyCallbackBase(callback, refCounter, subHalIndex) {}
+
+ Return<void> onDynamicSensorsConnected(
+ const hidl_vec<V1_0::SensorInfo>& dynamicSensorsAdded) override {
+ return mCallback->onDynamicSensorsConnected(
+ V2_1::implementation::convertToNewSensorInfos(dynamicSensorsAdded), mSubHalIndex);
+ }
+
+ Return<void> onDynamicSensorsDisconnected(
+ const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
+ return mCallback->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved, mSubHalIndex);
+ }
+
+ void postEvents(const std::vector<V1_0::Event>& events,
+ V2_0::implementation::ScopedWakelock wakelock) override {
+ HalProxyCallbackBase::postEvents(V2_1::implementation::convertToNewEvents(events),
+ std::move(wakelock));
+ }
+
+ V2_0::implementation::ScopedWakelock createScopedWakelock(bool lock) override {
+ return HalProxyCallbackBase::createScopedWakelock(lock);
+ }
+};
+
+class HalProxyCallbackV2_1 : public HalProxyCallbackBase,
+ public V2_1::implementation::IHalProxyCallback {
+ public:
+ HalProxyCallbackV2_1(ISubHalCallback* callback,
+ V2_0::implementation::IScopedWakelockRefCounter* refCounter,
+ int32_t subHalIndex)
+ : HalProxyCallbackBase(callback, refCounter, subHalIndex) {}
+
+ Return<void> onDynamicSensorsConnected_2_1(
+ const hidl_vec<V2_1::SensorInfo>& dynamicSensorsAdded) override {
+ return mCallback->onDynamicSensorsConnected(dynamicSensorsAdded, mSubHalIndex);
+ }
+
+ Return<void> onDynamicSensorsConnected(
+ const hidl_vec<V1_0::SensorInfo>& /* dynamicSensorsAdded */) override {
+ LOG_ALWAYS_FATAL("Old dynamic sensors method can't be used");
+ return Void();
+ }
+
+ Return<void> onDynamicSensorsDisconnected(
+ const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
+ return mCallback->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved, mSubHalIndex);
+ }
+
+ void postEvents(const std::vector<V2_1::Event>& events,
+ V2_0::implementation::ScopedWakelock wakelock) override {
+ return HalProxyCallbackBase::postEvents(events, std::move(wakelock));
+ }
+
+ V2_0::implementation::ScopedWakelock createScopedWakelock(bool lock) override {
+ return HalProxyCallbackBase::createScopedWakelock(lock);
+ }
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace sensors
+} // namespace hardware
+} // namespace android
\ No newline at end of file
diff --git a/sensors/common/default/2.X/multihal/include/SubHalWrapper.h b/sensors/common/default/2.X/multihal/include/SubHalWrapper.h
new file mode 100644
index 0000000..149bb5e
--- /dev/null
+++ b/sensors/common/default/2.X/multihal/include/SubHalWrapper.h
@@ -0,0 +1,188 @@
+/*
+ * 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 "HalProxyCallback.h"
+#include "V2_0/SubHal.h"
+#include "V2_1/SubHal.h"
+
+#include "android/hardware/sensors/1.0/ISensors.h"
+#include "android/hardware/sensors/1.0/types.h"
+#include "android/hardware/sensors/2.0/ISensors.h"
+#include "android/hardware/sensors/2.0/ISensorsCallback.h"
+#include "android/hardware/sensors/2.1/ISensors.h"
+#include "android/hardware/sensors/2.1/ISensorsCallback.h"
+#include "android/hardware/sensors/2.1/types.h"
+
+#include <utils/LightRefBase.h>
+
+#include <cassert>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_1 {
+namespace implementation {
+
+/**
+ * The following subHal wrapper classes abstract away common functionality across V2.0 and V2.1
+ * subHal interfaces. Much of the logic is common between the two versions and this allows users of
+ * the classes to only care about the type used at initialization and then interact with either
+ * version of the subHal interface without worrying about the type.
+ */
+class ISubHalWrapperBase {
+ protected:
+ using Event = ::android::hardware::sensors::V2_1::Event;
+ using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
+ using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
+ using Result = ::android::hardware::sensors::V1_0::Result;
+ using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
+ using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
+
+ public:
+ virtual ~ISubHalWrapperBase() {}
+
+ virtual bool supportsNewEvents() = 0;
+
+ virtual Return<Result> initialize(V2_0::implementation::ISubHalCallback* callback,
+ V2_0::implementation::IScopedWakelockRefCounter* refCounter,
+ int32_t subHalIndex) = 0;
+
+ virtual Return<void> getSensorsList(
+ ::android::hardware::sensors::V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) = 0;
+
+ virtual Return<Result> setOperationMode(OperationMode mode) = 0;
+
+ virtual Return<Result> activate(int32_t sensorHandle, bool enabled) = 0;
+
+ virtual Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) = 0;
+
+ virtual Return<Result> flush(int32_t sensorHandle) = 0;
+
+ virtual Return<Result> injectSensorData(const Event& event) = 0;
+
+ virtual Return<void> registerDirectChannel(const SharedMemInfo& mem,
+ ISensors::registerDirectChannel_cb _hidl_cb) = 0;
+
+ virtual Return<Result> unregisterDirectChannel(int32_t channelHandle) = 0;
+
+ virtual Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle,
+ RateLevel rate,
+ ISensors::configDirectReport_cb _hidl_cb) = 0;
+
+ virtual Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) = 0;
+
+ virtual const std::string getName() = 0;
+};
+
+template <typename T>
+class SubHalWrapperBase : public ISubHalWrapperBase {
+ public:
+ SubHalWrapperBase(T* subHal) : mSubHal(subHal){};
+
+ virtual bool supportsNewEvents() override { return false; }
+
+ virtual Return<void> getSensorsList(
+ ::android::hardware::sensors::V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) override {
+ return mSubHal->getSensorsList(
+ [&](const auto& list) { _hidl_cb(convertToNewSensorInfos(list)); });
+ }
+
+ Return<Result> setOperationMode(OperationMode mode) override {
+ return mSubHal->setOperationMode(mode);
+ }
+
+ Return<Result> activate(int32_t sensorHandle, bool enabled) override {
+ return mSubHal->activate(sensorHandle, enabled);
+ }
+
+ Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) override {
+ return mSubHal->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+ }
+
+ Return<Result> flush(int32_t sensorHandle) override { return mSubHal->flush(sensorHandle); }
+
+ virtual Return<Result> injectSensorData(const Event& event) override {
+ return mSubHal->injectSensorData(convertToOldEvent(event));
+ }
+
+ Return<void> registerDirectChannel(const SharedMemInfo& mem,
+ ISensors::registerDirectChannel_cb _hidl_cb) override {
+ return mSubHal->registerDirectChannel(mem, _hidl_cb);
+ }
+
+ Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+ return mSubHal->unregisterDirectChannel(channelHandle);
+ }
+
+ Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+ ISensors::configDirectReport_cb _hidl_cb) override {
+ return mSubHal->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+ }
+
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override {
+ return mSubHal->debug(fd, args);
+ }
+
+ const std::string getName() override { return mSubHal->getName(); }
+
+ protected:
+ T* mSubHal;
+};
+
+class SubHalWrapperV2_0 : public SubHalWrapperBase<V2_0::implementation::ISensorsSubHal> {
+ public:
+ SubHalWrapperV2_0(V2_0::implementation::ISensorsSubHal* subHal) : SubHalWrapperBase(subHal){};
+
+ Return<Result> initialize(V2_0::implementation::ISubHalCallback* callback,
+ V2_0::implementation::IScopedWakelockRefCounter* refCounter,
+ int32_t subHalIndex) override {
+ return mSubHal->initialize(
+ new V2_0::implementation::HalProxyCallbackV2_0(callback, refCounter, subHalIndex));
+ }
+};
+
+class SubHalWrapperV2_1 : public SubHalWrapperBase<V2_1::implementation::ISensorsSubHal> {
+ public:
+ SubHalWrapperV2_1(V2_1::implementation::ISensorsSubHal* subHal) : SubHalWrapperBase(subHal) {}
+
+ bool supportsNewEvents() override { return true; }
+
+ virtual Return<void> getSensorsList(
+ ::android::hardware::sensors::V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) override {
+ return mSubHal->getSensorsList_2_1([&](const auto& list) { _hidl_cb(list); });
+ }
+
+ virtual Return<Result> injectSensorData(const Event& event) override {
+ return mSubHal->injectSensorData_2_1(event);
+ }
+
+ Return<Result> initialize(V2_0::implementation::ISubHalCallback* callback,
+ V2_0::implementation::IScopedWakelockRefCounter* refCounter,
+ int32_t subHalIndex) override {
+ return mSubHal->initialize(
+ new V2_0::implementation::HalProxyCallbackV2_1(callback, refCounter, subHalIndex));
+ }
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace sensors
+} // namespace hardware
+} // namespace android
diff --git a/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h b/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
index aa6d9db..1cc5cd5 100644
--- a/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
+++ b/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
@@ -88,7 +88,7 @@
bool isLocked() const { return mLocked; }
private:
- friend class HalProxyCallback;
+ friend class HalProxyCallbackBase;
IScopedWakelockRefCounter* mRefCounter;
int64_t mCreatedAtTimeNs;
bool mLocked;
diff --git a/sensors/common/default/2.X/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
index 7692b51..a15faed 100644
--- a/sensors/common/default/2.X/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -20,6 +20,7 @@
],
header_libs: [
"android.hardware.sensors@2.0-multihal.header",
+ "android.hardware.sensors@2.X-shared-utils",
],
export_include_dirs: ["fake_subhal"],
shared_libs: [
@@ -36,6 +37,7 @@
"libutils",
],
static_libs: [
+ "android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.X-multihal",
],
cflags: [
@@ -48,6 +50,7 @@
vendor: true,
defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
+ "-DSUB_HAL_VERSION_2_0",
"-DSUPPORT_CONTINUOUS_SENSORS",
"-DSUB_HAL_NAME=\"FakeSubHal-Continuous\"",
],
@@ -58,6 +61,17 @@
vendor: true,
defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
+ "-DSUB_HAL_VERSION_2_0",
+ "-DSUPPORT_ON_CHANGE_SENSORS",
+ "-DSUB_HAL_NAME=\"FakeSubHal-OnChange\"",
+ ],
+}
+
+cc_library {
+ name: "android.hardware.sensors@2.X-fakesubhal-config3",
+ vendor: true,
+ defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
+ cflags: [
"-DSUPPORT_ON_CHANGE_SENSORS",
"-DSUB_HAL_NAME=\"FakeSubHal-OnChange\"",
],
@@ -78,7 +92,11 @@
name: "android.hardware.sensors@2.X-halproxy-unit-tests",
srcs: ["HalProxy_test.cpp"],
vendor: true,
+ header_libs: [
+ "android.hardware.sensors@2.X-shared-utils",
+ ],
static_libs: [
+ "android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.0-ScopedWakelock.testlib",
"android.hardware.sensors@2.X-multihal",
"android.hardware.sensors@2.X-fakesubhal-unittest",
@@ -86,7 +104,6 @@
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
- "android.hardware.sensors@2.0-ScopedWakelock",
"android.hardware.sensors@2.1",
"libbase",
"libcutils",
diff --git a/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
index 867c4a1..858786a 100644
--- a/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
+++ b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
@@ -15,12 +15,15 @@
#include <gtest/gtest.h>
+#include <android/hardware/sensors/1.0/types.h>
#include <android/hardware/sensors/2.0/types.h>
+#include <android/hardware/sensors/2.1/types.h>
#include <fmq/MessageQueue.h>
#include "HalProxy.h"
#include "SensorsSubHal.h"
#include "V2_0/ScopedWakelock.h"
+#include "convertV2_1.h"
#include <chrono>
#include <set>
@@ -38,27 +41,35 @@
using ::android::hardware::sensors::V1_0::SensorInfo;
using ::android::hardware::sensors::V1_0::SensorType;
using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
-using ::android::hardware::sensors::V2_0::ISensorsCallback;
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
-using ::android::hardware::sensors::V2_0::implementation::HalProxy;
-using ::android::hardware::sensors::V2_0::implementation::HalProxyCallback;
-using ::android::hardware::sensors::V2_0::subhal::implementation::AddAndRemoveDynamicSensorsSubHal;
-using ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal;
-using ::android::hardware::sensors::V2_0::subhal::implementation::
+using ::android::hardware::sensors::V2_0::implementation::HalProxyCallbackBase;
+using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock;
+using ::android::hardware::sensors::V2_1::implementation::convertToNewEvents;
+using ::android::hardware::sensors::V2_1::implementation::convertToNewSensorInfos;
+using ::android::hardware::sensors::V2_1::implementation::HalProxy;
+using ::android::hardware::sensors::V2_1::subhal::implementation::AddAndRemoveDynamicSensorsSubHal;
+using ::android::hardware::sensors::V2_1::subhal::implementation::AllSensorsSubHal;
+using ::android::hardware::sensors::V2_1::subhal::implementation::
AllSupportDirectChannelSensorsSubHal;
-using ::android::hardware::sensors::V2_0::subhal::implementation::ContinuousSensorsSubHal;
-using ::android::hardware::sensors::V2_0::subhal::implementation::
+using ::android::hardware::sensors::V2_1::subhal::implementation::ContinuousSensorsSubHal;
+using ::android::hardware::sensors::V2_1::subhal::implementation::
DoesNotSupportDirectChannelSensorsSubHal;
-using ::android::hardware::sensors::V2_0::subhal::implementation::OnChangeSensorsSubHal;
-using ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal;
-using ::android::hardware::sensors::V2_0::subhal::implementation::
+using ::android::hardware::sensors::V2_1::subhal::implementation::OnChangeSensorsSubHal;
+using ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_0;
+using ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_1;
+using ::android::hardware::sensors::V2_1::subhal::implementation::
SetOperationModeFailingSensorsSubHal;
-using EventMessageQueue = MessageQueue<Event, ::android::hardware::kSynchronizedReadWrite>;
+using ISensorsCallbackV2_0 = ::android::hardware::sensors::V2_0::ISensorsCallback;
+using ISensorsCallbackV2_1 = ::android::hardware::sensors::V2_1::ISensorsCallback;
+using EventV1_0 = ::android::hardware::sensors::V1_0::Event;
+using EventV2_1 = ::android::hardware::sensors::V2_1::Event;
+using EventMessageQueueV2_1 = MessageQueue<EventV2_1, ::android::hardware::kSynchronizedReadWrite>;
+using EventMessageQueueV2_0 = MessageQueue<EventV1_0, ::android::hardware::kSynchronizedReadWrite>;
using WakeupMessageQueue = MessageQueue<uint32_t, ::android::hardware::kSynchronizedReadWrite>;
// The barebones sensors callback class passed into halproxy initialize calls
-class SensorsCallback : public ISensorsCallback {
+class SensorsCallback : public ISensorsCallbackV2_0 {
public:
Return<void> onDynamicSensorsConnected(
const hidl_vec<SensorInfo>& /*dynamicSensorsAdded*/) override {
@@ -73,8 +84,30 @@
}
};
+class SensorsCallbackV2_1 : public ISensorsCallbackV2_1 {
+ public:
+ Return<void> onDynamicSensorsConnected_2_1(
+ const hidl_vec<::android::hardware::sensors::V2_1::SensorInfo>& /*dynamicSensorsAdded*/)
+ override {
+ // Nothing yet
+ return Return<void>();
+ }
+
+ Return<void> onDynamicSensorsConnected(
+ const hidl_vec<SensorInfo>& /*dynamicSensorsAdded*/) override {
+ // Nothing yet
+ return Return<void>();
+ }
+
+ Return<void> onDynamicSensorsDisconnected(
+ const hidl_vec<int32_t>& /*dynamicSensorHandlesRemoved*/) override {
+ // Nothing yet
+ return Return<void>();
+ }
+};
+
// The sensors callback that expects a variable list of sensors to be added
-class TestSensorsCallback : public ISensorsCallback {
+class TestSensorsCallback : public ISensorsCallbackV2_0 {
public:
Return<void> onDynamicSensorsConnected(
const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
@@ -129,10 +162,10 @@
void ackWakeupEventsToHalProxy(size_t numEvents, std::unique_ptr<WakeupMessageQueue>& wakelockQueue,
EventFlag* wakelockQueueFlag);
-bool readEventsOutOfQueue(size_t numEvents, std::unique_ptr<EventMessageQueue>& eventQueue,
+bool readEventsOutOfQueue(size_t numEvents, std::unique_ptr<EventMessageQueueV2_0>& eventQueue,
EventFlag* eventQueueFlag);
-std::unique_ptr<EventMessageQueue> makeEventFMQ(size_t size);
+std::unique_ptr<EventMessageQueueV2_0> makeEventFMQ(size_t size);
std::unique_ptr<WakeupMessageQueue> makeWakelockFMQ(size_t size);
@@ -142,7 +175,7 @@
*
* @return A proximity event.
*/
-Event makeProximityEvent();
+EventV1_0 makeProximityEvent();
/**
* Construct and return a HIDL Event type thats sensorHandle refers to a proximity sensor
@@ -150,7 +183,7 @@
*
* @return A proximity event.
*/
-Event makeAccelerometerEvent();
+EventV1_0 makeAccelerometerEvent();
/**
* Make a certain number of proximity type events with the sensorHandle field set to
@@ -160,7 +193,7 @@
*
* @return The created list of events.
*/
-std::vector<Event> makeMultipleProximityEvents(size_t numEvents);
+std::vector<EventV1_0> makeMultipleProximityEvents(size_t numEvents);
/**
* Make a certain number of accelerometer type events with the sensorHandle field set to
@@ -170,7 +203,7 @@
*
* @return The created list of events.
*/
-std::vector<Event> makeMultipleAccelerometerEvents(size_t numEvents);
+std::vector<EventV1_0> makeMultipleAccelerometerEvents(size_t numEvents);
/**
* Given a SensorInfo vector and a sensor handles vector populate 'sensors' with SensorInfo
@@ -188,7 +221,7 @@
// Tests follow
TEST(HalProxyTest, GetSensorsListOneSubHalTest) {
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> fakeSubHals{&subHal};
HalProxy proxy(fakeSubHals);
@@ -200,8 +233,8 @@
}
TEST(HalProxyTest, GetSensorsListTwoSubHalTest) {
- ContinuousSensorsSubHal continuousSubHal;
- OnChangeSensorsSubHal onChangeSubHal;
+ ContinuousSensorsSubHal<SensorsSubHalV2_0> continuousSubHal;
+ OnChangeSensorsSubHal<SensorsSubHalV2_0> onChangeSubHal;
std::vector<ISensorsSubHal*> fakeSubHals;
fakeSubHals.push_back(&continuousSubHal);
fakeSubHals.push_back(&onChangeSubHal);
@@ -221,8 +254,8 @@
}
TEST(HalProxyTest, SetOperationModeTwoSubHalSuccessTest) {
- ContinuousSensorsSubHal subHal1;
- OnChangeSensorsSubHal subHal2;
+ ContinuousSensorsSubHal<SensorsSubHalV2_0> subHal1;
+ OnChangeSensorsSubHal<SensorsSubHalV2_0> subHal2;
std::vector<ISensorsSubHal*> fakeSubHals{&subHal1, &subHal2};
HalProxy proxy(fakeSubHals);
@@ -238,7 +271,7 @@
}
TEST(HalProxyTest, SetOperationModeTwoSubHalFailTest) {
- AllSensorsSubHal subHal1;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal1;
SetOperationModeFailingSensorsSubHal subHal2;
std::vector<ISensorsSubHal*> fakeSubHals{&subHal1, &subHal2};
@@ -279,16 +312,16 @@
TEST(HalProxyTest, PostSingleNonWakeupEvent) {
constexpr size_t kQueueSize = 5;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events{makeAccelerometerEvent()};
- subHal.postEvents(events, false /* wakeup */);
+ std::vector<EventV1_0> events{makeAccelerometerEvent()};
+ subHal.postEvents(convertToNewEvents(events), false /* wakeup */);
EXPECT_EQ(eventQueue->availableToRead(), 1);
}
@@ -296,28 +329,28 @@
TEST(HalProxyTest, PostMultipleNonWakeupEvent) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumEvents = 3;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
- subHal.postEvents(events, false /* wakeup */);
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kNumEvents);
+ subHal.postEvents(convertToNewEvents(events), false /* wakeup */);
EXPECT_EQ(eventQueue->availableToRead(), kNumEvents);
}
TEST(HalProxyTest, PostSingleWakeupEvent) {
constexpr size_t kQueueSize = 5;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
EventFlag* eventQueueFlag;
@@ -326,8 +359,8 @@
EventFlag* wakelockQueueFlag;
EventFlag::createEventFlag(wakeLockQueue->getEventFlagWord(), &wakelockQueueFlag);
- std::vector<Event> events{makeProximityEvent()};
- subHal.postEvents(events, true /* wakeup */);
+ std::vector<EventV1_0> events{makeProximityEvent()};
+ subHal.postEvents(convertToNewEvents(events), true /* wakeup */);
EXPECT_EQ(eventQueue->availableToRead(), 1);
@@ -338,12 +371,12 @@
TEST(HalProxyTest, PostMultipleWakeupEvents) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumEvents = 3;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
EventFlag* eventQueueFlag;
@@ -352,8 +385,8 @@
EventFlag* wakelockQueueFlag;
EventFlag::createEventFlag(wakeLockQueue->getEventFlagWord(), &wakelockQueueFlag);
- std::vector<Event> events = makeMultipleProximityEvents(kNumEvents);
- subHal.postEvents(events, true /* wakeup */);
+ std::vector<EventV1_0> events = makeMultipleProximityEvents(kNumEvents);
+ subHal.postEvents(convertToNewEvents(events), true /* wakeup */);
EXPECT_EQ(eventQueue->availableToRead(), kNumEvents);
@@ -364,20 +397,20 @@
TEST(HalProxyTest, PostEventsMultipleSubhals) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumEvents = 2;
- AllSensorsSubHal subHal1, subHal2;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal1, subHal2;
std::vector<ISensorsSubHal*> subHals{&subHal1, &subHal2};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
- subHal1.postEvents(events, false /* wakeup */);
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kNumEvents);
+ subHal1.postEvents(convertToNewEvents(events), false /* wakeup */);
EXPECT_EQ(eventQueue->availableToRead(), kNumEvents);
- subHal2.postEvents(events, false /* wakeup */);
+ subHal2.postEvents(convertToNewEvents(events), false /* wakeup */);
EXPECT_EQ(eventQueue->availableToRead(), kNumEvents * 2);
}
@@ -385,19 +418,19 @@
TEST(HalProxyTest, PostEventsDelayedWrite) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumEvents = 6;
- AllSensorsSubHal subHal1, subHal2;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal1, subHal2;
std::vector<ISensorsSubHal*> subHals{&subHal1, &subHal2};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
EventFlag* eventQueueFlag;
EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag);
- std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
- subHal1.postEvents(events, false /* wakeup */);
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kNumEvents);
+ subHal1.postEvents(convertToNewEvents(events), false /* wakeup */);
EXPECT_EQ(eventQueue->availableToRead(), kQueueSize);
@@ -413,18 +446,20 @@
TEST(HalProxyTest, PostEventsMultipleSubhalsThreaded) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumEvents = 2;
- AllSensorsSubHal subHal1, subHal2;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal1, subHal2;
std::vector<ISensorsSubHal*> subHals{&subHal1, &subHal2};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kNumEvents);
- std::thread t1(&AllSensorsSubHal::postEvents, &subHal1, events, false);
- std::thread t2(&AllSensorsSubHal::postEvents, &subHal2, events, false);
+ std::thread t1(&AllSensorsSubHal<SensorsSubHalV2_0>::postEvents, &subHal1,
+ convertToNewEvents(events), false);
+ std::thread t2(&AllSensorsSubHal<SensorsSubHalV2_0>::postEvents, &subHal2,
+ convertToNewEvents(events), false);
t1.join();
t2.join();
@@ -435,34 +470,34 @@
TEST(HalProxyTest, DestructingWithEventsPendingOnBackgroundThread) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumEvents = 6;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
- subHal.postEvents(events, false /* wakeup */);
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kNumEvents);
+ subHal.postEvents(convertToNewEvents(events), false /* wakeup */);
// Destructing HalProxy object with events on the background thread
}
TEST(HalProxyTest, DestructingWithUnackedWakeupEventsPosted) {
constexpr size_t kQueueSize = 5;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events{makeProximityEvent()};
- subHal.postEvents(events, true /* wakeup */);
+ std::vector<EventV1_0> events{makeProximityEvent()};
+ subHal.postEvents(convertToNewEvents(events), true /* wakeup */);
// Not sending any acks back through wakeLockQueue
@@ -472,17 +507,17 @@
TEST(HalProxyTest, ReinitializeWithEventsPendingOnBackgroundThread) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumEvents = 10;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
- subHal.postEvents(events, false /* wakeup */);
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kNumEvents);
+ subHal.postEvents(convertToNewEvents(events), false /* wakeup */);
eventQueue = makeEventFMQ(kQueueSize);
wakeLockQueue = makeWakelockFMQ(kQueueSize);
@@ -492,23 +527,23 @@
EXPECT_EQ(secondInitResult, Result::OK);
// Small sleep so that pending writes thread has a change to hit writeBlocking call.
std::this_thread::sleep_for(std::chrono::milliseconds(5));
- Event eventOut;
+ EventV1_0 eventOut;
EXPECT_FALSE(eventQueue->read(&eventOut));
}
TEST(HalProxyTest, ReinitializingWithUnackedWakeupEventsPosted) {
constexpr size_t kQueueSize = 5;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- std::vector<Event> events{makeProximityEvent()};
- subHal.postEvents(events, true /* wakeup */);
+ std::vector<EventV1_0> events{makeProximityEvent()};
+ subHal.postEvents(convertToNewEvents(events), true /* wakeup */);
// Not sending any acks back through wakeLockQueue
@@ -523,12 +558,12 @@
TEST(HalProxyTest, InitializeManyTimesInARow) {
constexpr size_t kQueueSize = 5;
constexpr size_t kNumTimesToInit = 100;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
for (size_t i = 0; i < kNumTimesToInit; i++) {
@@ -540,15 +575,15 @@
TEST(HalProxyTest, OperationModeResetOnInitialize) {
constexpr size_t kQueueSize = 5;
- AllSensorsSubHal subHal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
proxy.setOperationMode(OperationMode::DATA_INJECTION);
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
- Event event = makeAccelerometerEvent();
+ EventV1_0 event = makeAccelerometerEvent();
// Should not be able to inject a non AdditionInfo type event because operation mode should
// have been reset to NORMAL
EXPECT_EQ(proxy.injectSensorData(event), Result::BAD_VALUE);
@@ -559,7 +594,7 @@
constexpr size_t kNumSensors = 5;
AddAndRemoveDynamicSensorsSubHal subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
HalProxy proxy(subHals);
@@ -574,9 +609,9 @@
}
TestSensorsCallback* callback = new TestSensorsCallback();
- ::android::sp<ISensorsCallback> callbackPtr = callback;
+ ::android::sp<ISensorsCallbackV2_0> callbackPtr = callback;
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
- subHal.addDynamicSensors(sensorsToConnect);
+ subHal.addDynamicSensors(convertToNewSensorInfos(sensorsToConnect));
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
subHal.removeDynamicSensors(sensorHandlesToAttemptToRemove);
@@ -593,7 +628,7 @@
AddAndRemoveDynamicSensorsSubHal subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(0);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(0);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(0);
std::vector<SensorInfo> sensorsToConnect;
@@ -602,9 +637,9 @@
sensorHandlesToExpect);
TestSensorsCallback* callback = new TestSensorsCallback();
- ::android::sp<ISensorsCallback> callbackPtr = callback;
+ ::android::sp<ISensorsCallbackV2_0> callbackPtr = callback;
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
- subHal.addDynamicSensors(sensorsToConnect);
+ subHal.addDynamicSensors(convertToNewSensorInfos(sensorsToConnect));
std::vector<SensorInfo> sensorsSeen = callback->getSensorsConnected();
EXPECT_EQ(kNumSensors, sensorsSeen.size());
@@ -621,7 +656,7 @@
AddAndRemoveDynamicSensorsSubHal subHal;
std::vector<ISensorsSubHal*> subHals{&subHal};
HalProxy proxy(subHals);
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(0);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(0);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(0);
std::vector<SensorInfo> sensorsToConnect;
@@ -646,9 +681,9 @@
nonDynamicSensorHandles.end());
TestSensorsCallback* callback = new TestSensorsCallback();
- ::android::sp<ISensorsCallback> callbackPtr = callback;
+ ::android::sp<ISensorsCallbackV2_0> callbackPtr = callback;
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
- subHal.addDynamicSensors(sensorsToConnect);
+ subHal.addDynamicSensors(convertToNewSensorInfos(sensorsToConnect));
subHal.removeDynamicSensors(sensorHandlesToAttemptToRemove);
std::vector<int32_t> sensorHandlesSeen = callback->getSensorHandlesDisconnected();
@@ -667,15 +702,15 @@
constexpr size_t kNumSubHals = 3;
constexpr size_t kQueueSize = 5;
int32_t kNumSubHalsInt32 = static_cast<int32_t>(kNumSubHals);
- std::vector<AllSensorsSubHal> subHalObjs(kNumSubHals);
+ std::vector<AllSensorsSubHal<SensorsSubHalV2_0>> subHalObjs(kNumSubHals);
std::vector<ISensorsSubHal*> subHals;
for (const auto& subHal : subHalObjs) {
subHals.push_back((ISensorsSubHal*)(&subHal));
}
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
// Initialize for the injectSensorData call so callback postEvents is valid
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
@@ -687,7 +722,7 @@
EXPECT_EQ(proxy.activate(0x00000001 | (kNumSubHalsInt32 << 24), true), Result::BAD_VALUE);
EXPECT_EQ(proxy.batch(0x00000001 | (kNumSubHalsInt32 << 24), 0, 0), Result::BAD_VALUE);
EXPECT_EQ(proxy.flush(0x00000001 | (kNumSubHalsInt32 << 24)), Result::BAD_VALUE);
- Event event;
+ EventV1_0 event;
event.sensorHandle = 0x00000001 | (kNumSubHalsInt32 << 24);
EXPECT_EQ(proxy.injectSensorData(event), Result::BAD_VALUE);
}
@@ -696,28 +731,28 @@
constexpr size_t kQueueSize = 5;
constexpr int32_t subhal1Index = 0;
constexpr int32_t subhal2Index = 1;
- AllSensorsSubHal subhal1;
- AllSensorsSubHal subhal2;
+ AllSensorsSubHal<SensorsSubHalV2_0> subhal1;
+ AllSensorsSubHal<SensorsSubHalV2_0> subhal2;
std::vector<ISensorsSubHal*> subHals{&subhal1, &subhal2};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> callback = new SensorsCallback();
HalProxy proxy(subHals);
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
int32_t sensorHandleToPost = 0x00000001;
- Event eventIn = makeAccelerometerEvent();
+ EventV1_0 eventIn = makeAccelerometerEvent();
eventIn.sensorHandle = sensorHandleToPost;
- std::vector<Event> eventsToPost{eventIn};
- subhal1.postEvents(eventsToPost, false);
+ std::vector<EventV1_0> eventsToPost{eventIn};
+ subhal1.postEvents(convertToNewEvents(eventsToPost), false);
- Event eventOut;
+ EventV1_0 eventOut;
EXPECT_TRUE(eventQueue->read(&eventOut));
EXPECT_EQ(eventOut.sensorHandle, (subhal1Index << 24) | sensorHandleToPost);
- subhal2.postEvents(eventsToPost, false);
+ subhal2.postEvents(convertToNewEvents(eventsToPost), false);
EXPECT_TRUE(eventQueue->read(&eventOut));
@@ -728,22 +763,22 @@
constexpr size_t kQueueSize = 5;
// TODO: Make this constant linked to same limit in HalProxy.h
constexpr size_t kMaxPendingQueueSize = 100000;
- AllSensorsSubHal subhal;
+ AllSensorsSubHal<SensorsSubHalV2_0> subhal;
std::vector<ISensorsSubHal*> subHals{&subhal};
- std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<EventMessageQueueV2_0> eventQueue = makeEventFMQ(kQueueSize);
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
- ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ ::android::sp<ISensorsCallbackV2_0> 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);
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kQueueSize);
+ subhal.postEvents(convertToNewEvents(events), false);
events = makeMultipleAccelerometerEvents(kMaxPendingQueueSize);
- subhal.postEvents(events, false);
+ subhal.postEvents(convertToNewEvents(events), false);
// Drain pending queue
for (int i = 0; i < kMaxPendingQueueSize + kQueueSize; i += kQueueSize) {
@@ -752,9 +787,9 @@
// Put one event on pending queue
events = makeMultipleAccelerometerEvents(kQueueSize);
- subhal.postEvents(events, false);
+ subhal.postEvents(convertToNewEvents(events), false);
events = {makeAccelerometerEvent()};
- subhal.postEvents(events, false);
+ subhal.postEvents(convertToNewEvents(events), false);
// Read out to make room for one event on pending queue to write to FMQ
ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
@@ -763,6 +798,35 @@
EXPECT_TRUE(readEventsOutOfQueue(1, eventQueue, eventQueueFlag));
}
+TEST(HalProxyTest, PostEventsMultipleSubhalsThreadedV2_1) {
+ constexpr size_t kQueueSize = 5;
+ constexpr size_t kNumEvents = 2;
+ AllSensorsSubHal<SensorsSubHalV2_0> subHal1;
+ AllSensorsSubHal<SensorsSubHalV2_1> subHal2;
+ std::vector<::android::hardware::sensors::V2_0::implementation::ISensorsSubHal*> subHalsV2_0{
+ &subHal1};
+ std::vector<::android::hardware::sensors::V2_1::implementation::ISensorsSubHal*> subHalsV2_1{
+ &subHal2};
+ HalProxy proxy(subHalsV2_0, subHalsV2_1);
+ std::unique_ptr<EventMessageQueueV2_1> eventQueue =
+ std::make_unique<EventMessageQueueV2_1>(kQueueSize, true);
+ std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
+ ::android::sp<ISensorsCallbackV2_1> callback = new SensorsCallbackV2_1();
+ proxy.initialize_2_1(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+ std::vector<EventV1_0> events = makeMultipleAccelerometerEvents(kNumEvents);
+
+ std::thread t1(&AllSensorsSubHal<SensorsSubHalV2_0>::postEvents, &subHal1,
+ convertToNewEvents(events), false);
+ std::thread t2(&AllSensorsSubHal<SensorsSubHalV2_1>::postEvents, &subHal2,
+ convertToNewEvents(events), false);
+
+ t1.join();
+ t2.join();
+
+ EXPECT_EQ(eventQueue->availableToRead(), kNumEvents * 2);
+}
+
// Helper implementations follow
void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
const std::vector<SensorInfo>& subHalSensorsList) {
@@ -801,26 +865,26 @@
wakelockQueueFlag->wake(static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN));
}
-bool readEventsOutOfQueue(size_t numEvents, std::unique_ptr<EventMessageQueue>& eventQueue,
+bool readEventsOutOfQueue(size_t numEvents, std::unique_ptr<EventMessageQueueV2_0>& eventQueue,
EventFlag* eventQueueFlag) {
constexpr int64_t kReadBlockingTimeout = INT64_C(500000000);
- std::vector<Event> events(numEvents);
+ std::vector<EventV1_0> events(numEvents);
return eventQueue->readBlocking(events.data(), numEvents,
static_cast<uint32_t>(EventQueueFlagBits::EVENTS_READ),
static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS),
kReadBlockingTimeout, eventQueueFlag);
}
-std::unique_ptr<EventMessageQueue> makeEventFMQ(size_t size) {
- return std::make_unique<EventMessageQueue>(size, true);
+std::unique_ptr<EventMessageQueueV2_0> makeEventFMQ(size_t size) {
+ return std::make_unique<EventMessageQueueV2_0>(size, true);
}
std::unique_ptr<WakeupMessageQueue> makeWakelockFMQ(size_t size) {
return std::make_unique<WakeupMessageQueue>(size, true);
}
-Event makeProximityEvent() {
- Event event;
+EventV1_0 makeProximityEvent() {
+ EventV1_0 event;
event.timestamp = 0xFF00FF00;
// This is the sensorhandle of proximity, which is wakeup type
event.sensorHandle = 0x00000008;
@@ -829,8 +893,8 @@
return event;
}
-Event makeAccelerometerEvent() {
- Event event;
+EventV1_0 makeAccelerometerEvent() {
+ EventV1_0 event;
event.timestamp = 0xFF00FF00;
// This is the sensorhandle of proximity, which is wakeup type
event.sensorHandle = 0x00000001;
@@ -839,16 +903,16 @@
return event;
}
-std::vector<Event> makeMultipleProximityEvents(size_t numEvents) {
- std::vector<Event> events;
+std::vector<EventV1_0> makeMultipleProximityEvents(size_t numEvents) {
+ std::vector<EventV1_0> events;
for (size_t i = 0; i < numEvents; i++) {
events.push_back(makeProximityEvent());
}
return events;
}
-std::vector<Event> makeMultipleAccelerometerEvents(size_t numEvents) {
- std::vector<Event> events;
+std::vector<EventV1_0> makeMultipleAccelerometerEvents(size_t numEvents) {
+ std::vector<EventV1_0> events;
for (size_t i = 0; i < numEvents; i++) {
events.push_back(makeAccelerometerEvent());
}
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/IHalProxyCallbackWrapper.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/IHalProxyCallbackWrapper.h
new file mode 100644
index 0000000..4542bfd
--- /dev/null
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/IHalProxyCallbackWrapper.h
@@ -0,0 +1,107 @@
+/*
+ * 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 "V2_0/SubHal.h"
+#include "V2_1/SubHal.h"
+#include "convertV2_1.h"
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_1 {
+namespace subhal {
+namespace implementation {
+
+/**
+ * The following callback wrapper classes abstract away common functionality across V2.0 and V2.1
+ * interfaces. Much of the logic is common between the two versions and this allows users of the
+ * classes to only care about the type used at initialization and then interact with either version
+ * of the callback interface without worrying about the type.
+ */
+class IHalProxyCallbackWrapperBase {
+ protected:
+ using ScopedWakelock = V2_0::implementation::ScopedWakelock;
+
+ public:
+ virtual ~IHalProxyCallbackWrapperBase() {}
+
+ virtual Return<void> onDynamicSensorsConnected(
+ const hidl_vec<V2_1::SensorInfo>& sensorInfos) = 0;
+
+ virtual Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& sensorHandles) = 0;
+
+ virtual void postEvents(const std::vector<V2_1::Event>& events, ScopedWakelock wakelock) = 0;
+
+ virtual ScopedWakelock createScopedWakelock(bool lock) = 0;
+};
+
+template <typename T>
+class HalProxyCallbackWrapperBase : public IHalProxyCallbackWrapperBase {
+ public:
+ HalProxyCallbackWrapperBase(sp<T> callback) : mCallback(callback){};
+
+ Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& sensorHandles) override {
+ return mCallback->onDynamicSensorsDisconnected(sensorHandles);
+ }
+
+ ScopedWakelock createScopedWakelock(bool lock) override {
+ return mCallback->createScopedWakelock(lock);
+ }
+
+ protected:
+ sp<T> mCallback;
+};
+
+class HalProxyCallbackWrapperV2_0
+ : public HalProxyCallbackWrapperBase<V2_0::implementation::IHalProxyCallback> {
+ public:
+ HalProxyCallbackWrapperV2_0(sp<V2_0::implementation::IHalProxyCallback> callback)
+ : HalProxyCallbackWrapperBase(callback){};
+
+ Return<void> onDynamicSensorsConnected(const hidl_vec<V2_1::SensorInfo>& sensorInfos) override {
+ return mCallback->onDynamicSensorsConnected(
+ V2_1::implementation::convertToOldSensorInfos(sensorInfos));
+ }
+
+ void postEvents(const std::vector<V2_1::Event>& events, ScopedWakelock wakelock) override {
+ return mCallback->postEvents(V2_1::implementation::convertToOldEvents(events),
+ std::move(wakelock));
+ }
+};
+
+class HalProxyCallbackWrapperV2_1
+ : public HalProxyCallbackWrapperBase<V2_1::implementation::IHalProxyCallback> {
+ public:
+ HalProxyCallbackWrapperV2_1(sp<V2_1::implementation::IHalProxyCallback> callback)
+ : HalProxyCallbackWrapperBase(callback){};
+
+ Return<void> onDynamicSensorsConnected(const hidl_vec<V2_1::SensorInfo>& sensorInfos) override {
+ return mCallback->onDynamicSensorsConnected_2_1(sensorInfos);
+ }
+
+ void postEvents(const std::vector<V2_1::Event>& events, ScopedWakelock wakelock) {
+ return mCallback->postEvents(events, std::move(wakelock));
+ }
+};
+
+} // namespace implementation
+} // namespace subhal
+} // namespace V2_1
+} // namespace sensors
+} // namespace hardware
+} // namespace android
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
index de89a00..1efd971 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
@@ -24,13 +24,18 @@
namespace android {
namespace hardware {
namespace sensors {
-namespace V2_0 {
+namespace V2_1 {
namespace subhal {
namespace implementation {
using ::android::hardware::sensors::V1_0::MetaDataEventType;
+using ::android::hardware::sensors::V1_0::OperationMode;
+using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorFlagBits;
using ::android::hardware::sensors::V1_0::SensorStatus;
+using ::android::hardware::sensors::V2_1::Event;
+using ::android::hardware::sensors::V2_1::SensorInfo;
+using ::android::hardware::sensors::V2_1::SensorType;
Sensor::Sensor(int32_t sensorHandle, ISensorsEventCallback* callback)
: mIsEnabled(false),
@@ -343,7 +348,7 @@
} // namespace implementation
} // namespace subhal
-} // namespace V2_0
+} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
index 60f5d3d..5cf9f83 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
@@ -16,7 +16,7 @@
#pragma once
-#include <android/hardware/sensors/1.0/types.h>
+#include <android/hardware/sensors/2.1/types.h>
#include <condition_variable>
#include <memory>
@@ -24,16 +24,16 @@
#include <thread>
#include <vector>
-using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::Result;
-using ::android::hardware::sensors::V1_0::SensorInfo;
-using ::android::hardware::sensors::V1_0::SensorType;
+using ::android::hardware::sensors::V2_1::Event;
+using ::android::hardware::sensors::V2_1::SensorInfo;
+using ::android::hardware::sensors::V2_1::SensorType;
namespace android {
namespace hardware {
namespace sensors {
-namespace V2_0 {
+namespace V2_1 {
namespace subhal {
namespace implementation {
@@ -151,7 +151,7 @@
} // namespace implementation
} // namespace subhal
-} // namespace V2_0
+} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp
index ff5ff38..20a4e9d 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp
@@ -16,33 +16,66 @@
#include "SensorsSubHal.h"
-#include <android/hardware/sensors/2.0/types.h>
+#include <android/hardware/sensors/2.1/types.h>
#include <log/log.h>
-ISensorsSubHal* sensorsHalGetSubHal(uint32_t* version) {
+#ifdef SUB_HAL_VERSION_2_0
+::android::hardware::sensors::V2_0::implementation::ISensorsSubHal* sensorsHalGetSubHal(
+ uint32_t* version) {
#if defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS
- static ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal subHal;
+ static ::android::hardware::sensors::V2_1::subhal::implementation::AllSensorsSubHal<
+ ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_0>
+ subHal;
#elif defined SUPPORT_CONTINUOUS_SENSORS
- static ::android::hardware::sensors::V2_0::subhal::implementation::ContinuousSensorsSubHal
+ static ::android::hardware::sensors::V2_1::subhal::implementation::ContinuousSensorsSubHal<
+ ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_0>
subHal;
#elif defined SUPPORT_ON_CHANGE_SENSORS
- static ::android::hardware::sensors::V2_0::subhal::implementation::OnChangeSensorsSubHal subHal;
+ static ::android::hardware::sensors::V2_1::subhal::implementation::OnChangeSensorsSubHal<
+ ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_0>
+ subHal;
#else
- static ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal subHal;
+ static ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHal<
+ ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_0>
+ subHal;
#endif // defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS
*version = SUB_HAL_2_0_VERSION;
return &subHal;
}
+#else // SUB_HAL_VERSION_2_0
+
+::android::hardware::sensors::V2_1::implementation::ISensorsSubHal* sensorsHalGetSubHal_2_1(
+ uint32_t* version) {
+#if defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS
+ static ::android::hardware::sensors::V2_1::subhal::implementation::AllSensorsSubHal<
+ ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_1>
+ subHal;
+#elif defined SUPPORT_CONTINUOUS_SENSORS
+ static ::android::hardware::sensors::V2_1::subhal::implementation::ContinuousSensorsSubHal<
+ ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_1>
+ subHal;
+#elif defined SUPPORT_ON_CHANGE_SENSORS
+ static ::android::hardware::sensors::V2_1::subhal::implementation::OnChangeSensorsSubHal<
+ ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_1>
+ subHal;
+#else
+ static ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHalV2_1 subHal;
+#endif // defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS
+ *version = SUB_HAL_2_1_VERSION;
+ return &subHal;
+}
+
+#endif // SUB_HAL_VERSION_2_0
+
namespace android {
namespace hardware {
namespace sensors {
-namespace V2_0 {
+namespace V2_1 {
namespace subhal {
namespace implementation {
using ::android::hardware::Void;
-using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::Result;
@@ -50,11 +83,12 @@
using ::android::hardware::sensors::V2_0::SensorTimeout;
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock;
+using ::android::hardware::sensors::V2_1::Event;
-SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {}
+ISensorsSubHalBase::ISensorsSubHalBase() : mCallback(nullptr), mNextHandle(1) {}
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
-Return<void> SensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) {
+Return<void> ISensorsSubHalBase::getSensorsList(V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) {
std::vector<SensorInfo> sensors;
for (const auto& sensor : mSensors) {
sensors.push_back(sensor.second->getSensorInfo());
@@ -64,7 +98,7 @@
return Void();
}
-Return<Result> SensorsSubHal::setOperationMode(OperationMode mode) {
+Return<Result> ISensorsSubHalBase::setOperationMode(OperationMode mode) {
for (auto sensor : mSensors) {
sensor.second->setOperationMode(mode);
}
@@ -72,7 +106,7 @@
return Result::OK;
}
-Return<Result> SensorsSubHal::activate(int32_t sensorHandle, bool enabled) {
+Return<Result> ISensorsSubHalBase::activate(int32_t sensorHandle, bool enabled) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->activate(enabled);
@@ -81,8 +115,8 @@
return Result::BAD_VALUE;
}
-Return<Result> SensorsSubHal::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
- int64_t /* maxReportLatencyNs */) {
+Return<Result> ISensorsSubHalBase::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t /* maxReportLatencyNs */) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->batch(samplingPeriodNs);
@@ -91,7 +125,7 @@
return Result::BAD_VALUE;
}
-Return<Result> SensorsSubHal::flush(int32_t sensorHandle) {
+Return<Result> ISensorsSubHalBase::flush(int32_t sensorHandle) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
return sensor->second->flush();
@@ -99,7 +133,7 @@
return Result::BAD_VALUE;
}
-Return<Result> SensorsSubHal::injectSensorData(const Event& event) {
+Return<Result> ISensorsSubHalBase::injectSensorData(const Event& event) {
auto sensor = mSensors.find(event.sensorHandle);
if (sensor != mSensors.end()) {
return sensor->second->injectEvent(event);
@@ -108,24 +142,24 @@
return Result::BAD_VALUE;
}
-Return<void> SensorsSubHal::registerDirectChannel(const SharedMemInfo& /* mem */,
- registerDirectChannel_cb _hidl_cb) {
+Return<void> ISensorsSubHalBase::registerDirectChannel(
+ const SharedMemInfo& /* mem */, V2_0::ISensors::registerDirectChannel_cb _hidl_cb) {
_hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
return Return<void>();
}
-Return<Result> SensorsSubHal::unregisterDirectChannel(int32_t /* channelHandle */) {
+Return<Result> ISensorsSubHalBase::unregisterDirectChannel(int32_t /* channelHandle */) {
return Result::INVALID_OPERATION;
}
-Return<void> SensorsSubHal::configDirectReport(int32_t /* sensorHandle */,
- int32_t /* channelHandle */, RateLevel /* rate */,
- configDirectReport_cb _hidl_cb) {
+Return<void> ISensorsSubHalBase::configDirectReport(
+ int32_t /* sensorHandle */, int32_t /* channelHandle */, RateLevel /* rate */,
+ V2_0::ISensors::configDirectReport_cb _hidl_cb) {
_hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
return Return<void>();
}
-Return<void> SensorsSubHal::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
+Return<void> ISensorsSubHalBase::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
ALOGE("%s: missing fd for writing", __FUNCTION__);
return Void();
@@ -156,44 +190,18 @@
return Return<void>();
}
-Return<Result> SensorsSubHal::initialize(const sp<IHalProxyCallback>& halProxyCallback) {
- mCallback = halProxyCallback;
+Return<Result> ISensorsSubHalBase::initialize(
+ std::unique_ptr<IHalProxyCallbackWrapperBase>& halProxyCallback) {
+ mCallback = std::move(halProxyCallback);
setOperationMode(OperationMode::NORMAL);
return Result::OK;
}
-void SensorsSubHal::postEvents(const std::vector<Event>& events, bool wakeup) {
+void ISensorsSubHalBase::postEvents(const std::vector<Event>& events, bool wakeup) {
ScopedWakelock wakelock = mCallback->createScopedWakelock(wakeup);
mCallback->postEvents(events, std::move(wakelock));
}
-ContinuousSensorsSubHal::ContinuousSensorsSubHal() {
- AddSensor<AccelSensor>();
- AddSensor<GyroSensor>();
- AddSensor<MagnetometerSensor>();
- AddSensor<PressureSensor>();
- AddSensor<DeviceTempSensor>();
-}
-
-OnChangeSensorsSubHal::OnChangeSensorsSubHal() {
- AddSensor<AmbientTempSensor>();
- AddSensor<LightSensor>();
- AddSensor<ProximitySensor>();
- AddSensor<RelativeHumiditySensor>();
-}
-
-AllSensorsSubHal::AllSensorsSubHal() {
- AddSensor<AccelSensor>();
- AddSensor<GyroSensor>();
- AddSensor<MagnetometerSensor>();
- AddSensor<PressureSensor>();
- AddSensor<DeviceTempSensor>();
- AddSensor<AmbientTempSensor>();
- AddSensor<LightSensor>();
- AddSensor<ProximitySensor>();
- AddSensor<RelativeHumiditySensor>();
-}
-
Return<Result> SetOperationModeFailingSensorsSubHal::setOperationMode(OperationMode /*mode*/) {
return Result::BAD_VALUE;
}
@@ -206,7 +214,7 @@
sensorInfo.flags |= V1_0::SensorFlagBits::MASK_DIRECT_REPORT;
sensors.push_back(sensorInfo);
}
- _hidl_cb(sensors);
+ _hidl_cb(V2_1::implementation::convertToOldSensorInfos(sensors));
return Void();
}
@@ -218,7 +226,7 @@
sensorInfo.flags &= ~static_cast<uint32_t>(V1_0::SensorFlagBits::MASK_DIRECT_REPORT);
sensors.push_back(sensorInfo);
}
- _hidl_cb(sensors);
+ _hidl_cb(V2_1::implementation::convertToOldSensorInfos(sensors));
return Void();
}
@@ -234,7 +242,7 @@
} // namespace implementation
} // namespace subhal
-} // namespace V2_0
+} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
index 6da4404..1a78e84 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
@@ -17,7 +17,9 @@
#pragma once
#include "V2_0/SubHal.h"
+#include "V2_1/SubHal.h"
+#include "IHalProxyCallbackWrapper.h"
#include "Sensor.h"
#include <vector>
@@ -25,54 +27,54 @@
namespace android {
namespace hardware {
namespace sensors {
-namespace V2_0 {
+namespace V2_1 {
namespace subhal {
namespace implementation {
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::Result;
-using ::android::hardware::sensors::V2_0::implementation::IHalProxyCallback;
/**
* Implementation of a ISensorsSubHal that can be used to test the implementation of multihal 2.0.
* See the README file for more details on how this class can be used for testing.
*/
-class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback {
- using Event = ::android::hardware::sensors::V1_0::Event;
+class ISensorsSubHalBase : public ISensorsEventCallback {
+ protected:
+ using Event = ::android::hardware::sensors::V2_1::Event;
using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
public:
- SensorsSubHal();
+ ISensorsSubHalBase();
+
+ Return<void> getSensorsList(V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb);
+ Return<Result> injectSensorData(const Event& event);
+ Return<Result> initialize(std::unique_ptr<IHalProxyCallbackWrapperBase>& halProxyCallback);
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
- virtual Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
-
- virtual Return<Result> setOperationMode(OperationMode mode) override;
+ virtual Return<Result> setOperationMode(OperationMode mode);
OperationMode getOperationMode() const { return mCurrentOperationMode; }
- Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+ Return<Result> activate(int32_t sensorHandle, bool enabled);
Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
- int64_t maxReportLatencyNs) override;
+ int64_t maxReportLatencyNs);
- Return<Result> flush(int32_t sensorHandle) override;
-
- Return<Result> injectSensorData(const Event& event) override;
+ Return<Result> flush(int32_t sensorHandle);
Return<void> registerDirectChannel(const SharedMemInfo& mem,
- registerDirectChannel_cb _hidl_cb) override;
+ V2_0::ISensors::registerDirectChannel_cb _hidl_cb);
- Return<Result> unregisterDirectChannel(int32_t channelHandle) override;
+ Return<Result> unregisterDirectChannel(int32_t channelHandle);
Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
- configDirectReport_cb _hidl_cb) override;
+ V2_0::ISensors::configDirectReport_cb _hidl_cb);
- Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args);
// Methods from ::android::hardware::sensors::V2_0::implementation::ISensorsSubHal follow.
- const std::string getName() override {
+ const std::string getName() {
#ifdef SUB_HAL_NAME
return SUB_HAL_NAME;
#else // SUB_HAL_NAME
@@ -80,8 +82,6 @@
#endif // SUB_HAL_NAME
}
- Return<Result> initialize(const sp<IHalProxyCallback>& halProxyCallback) override;
-
// Method from ISensorsEventCallback.
void postEvents(const std::vector<Event>& events, bool wakeup) override;
@@ -103,7 +103,7 @@
* disconnected, sensor events need to be sent to the framework, and when a wakelock should be
* acquired.
*/
- sp<IHalProxyCallback> mCallback;
+ std::unique_ptr<IHalProxyCallbackWrapperBase> mCallback;
private:
/**
@@ -118,40 +118,143 @@
int32_t mNextHandle;
};
-// SubHal that has continuous sensors for testing purposes.
-class ContinuousSensorsSubHal : public SensorsSubHal {
+template <class SubHalClass>
+class SensorsSubHalBase : public ISensorsSubHalBase, public SubHalClass {
public:
- ContinuousSensorsSubHal();
+ Return<Result> setOperationMode(OperationMode mode) override {
+ return ISensorsSubHalBase::setOperationMode(mode);
+ }
+
+ Return<Result> activate(int32_t sensorHandle, bool enabled) override {
+ return ISensorsSubHalBase::activate(sensorHandle, enabled);
+ }
+
+ Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) override {
+ return ISensorsSubHalBase::batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+ }
+
+ Return<Result> flush(int32_t sensorHandle) override {
+ return ISensorsSubHalBase::flush(sensorHandle);
+ }
+
+ Return<void> registerDirectChannel(const SharedMemInfo& mem,
+ V2_0::ISensors::registerDirectChannel_cb _hidl_cb) override {
+ return ISensorsSubHalBase::registerDirectChannel(mem, _hidl_cb);
+ }
+
+ Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+ return ISensorsSubHalBase::unregisterDirectChannel(channelHandle);
+ }
+
+ Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+ V2_0::ISensors::configDirectReport_cb _hidl_cb) override {
+ return ISensorsSubHalBase::configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+ }
+
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override {
+ return ISensorsSubHalBase::debug(fd, args);
+ }
+
+ const std::string getName() override { return ISensorsSubHalBase::getName(); }
+};
+
+class SensorsSubHalV2_0 : public SensorsSubHalBase<V2_0::implementation::ISensorsSubHal> {
+ public:
+ virtual Return<void> getSensorsList(V2_0::ISensors::getSensorsList_cb _hidl_cb) override {
+ return ISensorsSubHalBase::getSensorsList([&](const auto& list) {
+ _hidl_cb(V2_1::implementation::convertToOldSensorInfos(list));
+ });
+ }
+
+ Return<Result> injectSensorData(const V1_0::Event& event) override {
+ return ISensorsSubHalBase::injectSensorData(V2_1::implementation::convertToNewEvent(event));
+ }
+
+ Return<Result> initialize(
+ const sp<V2_0::implementation::IHalProxyCallback>& halProxyCallback) override {
+ std::unique_ptr<IHalProxyCallbackWrapperBase> wrapper =
+ std::make_unique<HalProxyCallbackWrapperV2_0>(halProxyCallback);
+ return ISensorsSubHalBase::initialize(wrapper);
+ }
+};
+
+class SensorsSubHalV2_1 : public SensorsSubHalBase<V2_1::implementation::ISensorsSubHal> {
+ public:
+ Return<void> getSensorsList_2_1(V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) override {
+ return ISensorsSubHalBase::getSensorsList(_hidl_cb);
+ }
+
+ Return<Result> injectSensorData_2_1(const V2_1::Event& event) override {
+ return ISensorsSubHalBase::injectSensorData(event);
+ }
+
+ Return<Result> initialize(
+ const sp<V2_1::implementation::IHalProxyCallback>& halProxyCallback) override {
+ std::unique_ptr<IHalProxyCallbackWrapperBase> wrapper =
+ std::make_unique<HalProxyCallbackWrapperV2_1>(halProxyCallback);
+ return ISensorsSubHalBase::initialize(wrapper);
+ }
+};
+
+// SubHal that has continuous sensors for testing purposes.
+template <class SubHalVersion>
+class ContinuousSensorsSubHal : public SubHalVersion {
+ public:
+ ContinuousSensorsSubHal() {
+ ISensorsSubHalBase::AddSensor<AccelSensor>();
+ ISensorsSubHalBase::AddSensor<GyroSensor>();
+ ISensorsSubHalBase::AddSensor<MagnetometerSensor>();
+ ISensorsSubHalBase::AddSensor<PressureSensor>();
+ ISensorsSubHalBase::AddSensor<DeviceTempSensor>();
+ }
};
// SubHal that has on-change sensors for testing purposes.
-class OnChangeSensorsSubHal : public SensorsSubHal {
+template <class SubHalVersion>
+class OnChangeSensorsSubHal : public SubHalVersion {
public:
- OnChangeSensorsSubHal();
+ OnChangeSensorsSubHal() {
+ ISensorsSubHalBase::AddSensor<AmbientTempSensor>();
+ ISensorsSubHalBase::AddSensor<LightSensor>();
+ ISensorsSubHalBase::AddSensor<ProximitySensor>();
+ ISensorsSubHalBase::AddSensor<RelativeHumiditySensor>();
+ }
};
// SubHal that has both continuous and on-change sensors for testing purposes.
-class AllSensorsSubHal : public SensorsSubHal {
+template <class SubHalVersion>
+class AllSensorsSubHal : public SubHalVersion {
public:
- AllSensorsSubHal();
+ AllSensorsSubHal() {
+ ISensorsSubHalBase::AddSensor<AccelSensor>();
+ ISensorsSubHalBase::AddSensor<GyroSensor>();
+ ISensorsSubHalBase::AddSensor<MagnetometerSensor>();
+ ISensorsSubHalBase::AddSensor<PressureSensor>();
+ ISensorsSubHalBase::AddSensor<DeviceTempSensor>();
+ ISensorsSubHalBase::AddSensor<AmbientTempSensor>();
+ ISensorsSubHalBase::AddSensor<LightSensor>();
+ ISensorsSubHalBase::AddSensor<ProximitySensor>();
+ ISensorsSubHalBase::AddSensor<RelativeHumiditySensor>();
+ }
};
-class SetOperationModeFailingSensorsSubHal : public AllSensorsSubHal {
+class SetOperationModeFailingSensorsSubHal : public AllSensorsSubHal<SensorsSubHalV2_0> {
public:
Return<Result> setOperationMode(OperationMode mode) override;
};
-class AllSupportDirectChannelSensorsSubHal : public AllSensorsSubHal {
+class AllSupportDirectChannelSensorsSubHal : public AllSensorsSubHal<SensorsSubHalV2_0> {
public:
- Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+ Return<void> getSensorsList(V2_0::ISensors::getSensorsList_cb _hidl_cb) override;
};
-class DoesNotSupportDirectChannelSensorsSubHal : public AllSensorsSubHal {
+class DoesNotSupportDirectChannelSensorsSubHal : public AllSensorsSubHal<SensorsSubHalV2_0> {
public:
- Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+ Return<void> getSensorsList(V2_0::ISensors::getSensorsList_cb _hidl_cb) override;
};
-class AddAndRemoveDynamicSensorsSubHal : public AllSensorsSubHal {
+class AddAndRemoveDynamicSensorsSubHal : public AllSensorsSubHal<SensorsSubHalV2_0> {
public:
void addDynamicSensors(const std::vector<SensorInfo>& sensorsAdded);
void removeDynamicSensors(const std::vector<int32_t>& sensorHandlesAdded);
@@ -159,7 +262,7 @@
} // namespace implementation
} // namespace subhal
-} // namespace V2_0
+} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
diff --git a/sensors/common/utils/EventMessageQueueWrapper.h b/sensors/common/utils/EventMessageQueueWrapper.h
index bf3261f..c4f92c8 100644
--- a/sensors/common/utils/EventMessageQueueWrapper.h
+++ b/sensors/common/utils/EventMessageQueueWrapper.h
@@ -39,8 +39,14 @@
virtual std::atomic<uint32_t>* getEventFlagWord() = 0;
virtual size_t availableToRead() = 0;
+ virtual size_t availableToWrite() = 0;
virtual bool read(V2_1::Event* events, size_t numToRead) = 0;
+ virtual bool write(const V2_1::Event* events, size_t numToWrite) = 0;
virtual bool write(const std::vector<V2_1::Event>& events) = 0;
+ virtual bool writeBlocking(const V2_1::Event* events, size_t count, uint32_t readNotification,
+ uint32_t writeNotification, int64_t timeOutNanos,
+ android::hardware::EventFlag* evFlag) = 0;
+ virtual size_t getQuantumCount() = 0;
};
class EventMessageQueueWrapperV1_0 : public EventMessageQueueWrapperBase {
@@ -60,15 +66,30 @@
virtual size_t availableToRead() override { return mQueue->availableToRead(); }
+ size_t availableToWrite() override { return mQueue->availableToWrite(); }
+
virtual bool read(V2_1::Event* events, size_t numToRead) override {
return mQueue->read(reinterpret_cast<V1_0::Event*>(events), numToRead);
}
+ bool write(const V2_1::Event* events, size_t numToWrite) override {
+ return mQueue->write(reinterpret_cast<const V1_0::Event*>(events), numToWrite);
+ }
+
virtual bool write(const std::vector<V2_1::Event>& events) override {
const std::vector<V1_0::Event>& oldEvents = convertToOldEvents(events);
return mQueue->write(oldEvents.data(), oldEvents.size());
}
+ bool writeBlocking(const V2_1::Event* events, size_t count, uint32_t readNotification,
+ uint32_t writeNotification, int64_t timeOutNanos,
+ android::hardware::EventFlag* evFlag) override {
+ return mQueue->writeBlocking(reinterpret_cast<const V1_0::Event*>(events), count,
+ readNotification, writeNotification, timeOutNanos, evFlag);
+ }
+
+ size_t getQuantumCount() override { return mQueue->getQuantumCount(); }
+
private:
std::unique_ptr<EventMessageQueue> mQueue;
};
@@ -88,14 +109,29 @@
virtual size_t availableToRead() override { return mQueue->availableToRead(); }
+ size_t availableToWrite() override { return mQueue->availableToWrite(); }
+
virtual bool read(V2_1::Event* events, size_t numToRead) override {
return mQueue->read(events, numToRead);
}
+ bool write(const V2_1::Event* events, size_t numToWrite) override {
+ return mQueue->write(events, numToWrite);
+ }
+
bool write(const std::vector<V2_1::Event>& events) override {
return mQueue->write(events.data(), events.size());
}
+ bool writeBlocking(const V2_1::Event* events, size_t count, uint32_t readNotification,
+ uint32_t writeNotification, int64_t timeOutNanos,
+ android::hardware::EventFlag* evFlag) override {
+ return mQueue->writeBlocking(events, count, readNotification, writeNotification,
+ timeOutNanos, evFlag);
+ }
+
+ size_t getQuantumCount() override { return mQueue->getQuantumCount(); }
+
private:
std::unique_ptr<EventMessageQueue> mQueue;
};
diff --git a/sensors/common/utils/ISensorsCallbackWrapper.h b/sensors/common/utils/ISensorsCallbackWrapper.h
new file mode 100644
index 0000000..816b225
--- /dev/null
+++ b/sensors/common/utils/ISensorsCallbackWrapper.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_SENSORS_V2_1_ISENSORSCALLBACKWRAPPER_H
+#define ANDROID_HARDWARE_SENSORS_V2_1_ISENSORSCALLBACKWRAPPER_H
+
+#include "convertV2_1.h"
+
+#include "android/hardware/sensors/1.0/ISensors.h"
+#include "android/hardware/sensors/1.0/types.h"
+#include "android/hardware/sensors/2.0/ISensors.h"
+#include "android/hardware/sensors/2.0/ISensorsCallback.h"
+#include "android/hardware/sensors/2.1/ISensors.h"
+#include "android/hardware/sensors/2.1/ISensorsCallback.h"
+#include "android/hardware/sensors/2.1/types.h"
+
+#include <utils/LightRefBase.h>
+
+#include <cassert>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_1 {
+namespace implementation {
+
+/**
+ * The ISensorsCallbackWrapper classes below abstract away the common logic between both the V2.0
+ * and V2.1 versions of the Sensors HAL interface. This allows users of these classes to only care
+ * about the HAL version at init time and then interact with either version of the callback without
+ * worrying about the class type by utilizing the base class.
+ */
+class ISensorsCallbackWrapperBase : public VirtualLightRefBase {
+ public:
+ virtual Return<void> onDynamicSensorsConnected(
+ const hidl_vec<V2_1::SensorInfo>& sensorInfos) = 0;
+
+ virtual Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& sensorHandles) = 0;
+};
+
+template <typename T>
+class SensorsCallbackWrapperBase : public ISensorsCallbackWrapperBase {
+ public:
+ SensorsCallbackWrapperBase(sp<T> sensorsCallback) : mSensorsCallback(sensorsCallback){};
+
+ virtual Return<void> onDynamicSensorsConnected(
+ const hidl_vec<V2_1::SensorInfo>& sensorInfos) override {
+ return mSensorsCallback->onDynamicSensorsConnected(convertToOldSensorInfos(sensorInfos));
+ }
+
+ Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& sensorHandles) {
+ return mSensorsCallback->onDynamicSensorsDisconnected(sensorHandles);
+ }
+
+ protected:
+ sp<T> mSensorsCallback;
+};
+
+class ISensorsCallbackWrapperV2_0
+ : public SensorsCallbackWrapperBase<hardware::sensors::V2_0::ISensorsCallback> {
+ public:
+ ISensorsCallbackWrapperV2_0(sp<hardware::sensors::V2_0::ISensorsCallback> sensorsCallback)
+ : SensorsCallbackWrapperBase(sensorsCallback){};
+};
+
+class ISensorsCallbackWrapperV2_1
+ : public SensorsCallbackWrapperBase<hardware::sensors::V2_1::ISensorsCallback> {
+ public:
+ ISensorsCallbackWrapperV2_1(sp<hardware::sensors::V2_1::ISensorsCallback> sensorsCallback)
+ : SensorsCallbackWrapperBase(sensorsCallback) {}
+
+ Return<void> onDynamicSensorsConnected(const hidl_vec<V2_1::SensorInfo>& sensorInfos) override {
+ return mSensorsCallback->onDynamicSensorsConnected_2_1(sensorInfos);
+ }
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace sensors
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_SENSORS_V2_1_ISENSORSCALLBACKWRAPPER_H
\ No newline at end of file
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 745ab2d..75f2c28 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -737,6 +737,8 @@
callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
activateAllSensors(false);
+ getEnvironment()->unregisterCallback();
+
for (const SensorInfoType& sensor : sensors) {
// Skip sensors that did not previously report an event
if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) {
diff --git a/soundtrigger/2.0/vts/functional/Android.bp b/soundtrigger/2.0/vts/functional/Android.bp
index 13dcdec..86697bd 100644
--- a/soundtrigger/2.0/vts/functional/Android.bp
+++ b/soundtrigger/2.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalSoundtriggerV2_0TargetTest.cpp"],
static_libs: ["android.hardware.soundtrigger@2.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/soundtrigger/2.1/vts/functional/Android.bp b/soundtrigger/2.1/vts/functional/Android.bp
index 7830fe2..9de913b 100644
--- a/soundtrigger/2.1/vts/functional/Android.bp
+++ b/soundtrigger/2.1/vts/functional/Android.bp
@@ -25,5 +25,5 @@
"android.hardware.soundtrigger@2.1",
"libhidlmemory"
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp
index b5d241d..b7967d9 100644
--- a/soundtrigger/2.2/vts/functional/Android.bp
+++ b/soundtrigger/2.2/vts/functional/Android.bp
@@ -23,5 +23,5 @@
"android.hardware.soundtrigger@2.1",
"android.hardware.soundtrigger@2.2",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/soundtrigger/2.3/vts/functional/Android.bp b/soundtrigger/2.3/vts/functional/Android.bp
index e3855fc..2c1b9e5 100644
--- a/soundtrigger/2.3/vts/functional/Android.bp
+++ b/soundtrigger/2.3/vts/functional/Android.bp
@@ -26,6 +26,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp
index 42e0a92..c64779c 100644
--- a/tests/extension/vibrator/aidl/Android.bp
+++ b/tests/extension/vibrator/aidl/Android.bp
@@ -1,7 +1,7 @@
aidl_interface {
// This is an example test interface showing how to add functionality
// with setExtension/getExtension
- name: "test-android.hardware.vibrator-ext",
+ name: "android.hardware.tests.extension.vibrator",
vendor_available: true,
srcs: [
// Using android.hardware as the package because this is in
@@ -26,4 +26,5 @@
enabled: false,
},
},
+ versions: ["1"],
}
diff --git a/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/.hash b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/.hash
new file mode 100644
index 0000000..7df2790
--- /dev/null
+++ b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/.hash
@@ -0,0 +1 @@
+86dfe4cf135ed1bf501e7e8408bcee3b590e8a53
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/Directionality.aidl b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/android/hardware/tests/extension/vibrator/Directionality.aidl
similarity index 100%
rename from tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/Directionality.aidl
rename to tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/android/hardware/tests/extension/vibrator/Directionality.aidl
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
similarity index 100%
rename from tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
rename to tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/android/hardware/tests/extension/vibrator/VendorEffect.aidl
similarity index 100%
rename from tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl
rename to tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/1/android/hardware/tests/extension/vibrator/VendorEffect.aidl
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/Directionality.aidl b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/current/android/hardware/tests/extension/vibrator/Directionality.aidl
similarity index 100%
copy from tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/Directionality.aidl
copy to tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/current/android/hardware/tests/extension/vibrator/Directionality.aidl
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
similarity index 100%
copy from tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
copy to tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl b/tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl
similarity index 100%
copy from tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl
copy to tests/extension/vibrator/aidl/aidl_api/android.hardware.tests.extension.vibrator/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl
diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp
index c707dbe..b0d8238 100644
--- a/tests/extension/vibrator/aidl/client/Android.bp
+++ b/tests/extension/vibrator/aidl/client/Android.bp
@@ -3,7 +3,7 @@
// server for example.
cc_test {
- name: "test-android.hardware.vibrator-ext-client",
+ name: "android.hardware.tests.extension.vibrator-client",
srcs: [
// system code has the option to use the unstable C++ libbinder API
// or the NDK one. For maximum code portability, using the ndk client
@@ -15,10 +15,10 @@
"libbinder",
"libutils",
"android.hardware.vibrator-cpp",
- "test-android.hardware.vibrator-ext-cpp",
+ "android.hardware.tests.extension.vibrator-cpp",
"libbinder_ndk",
"android.hardware.vibrator-ndk_platform",
- "test-android.hardware.vibrator-ext-ndk_platform",
+ "android.hardware.tests.extension.vibrator-ndk_platform",
],
}
diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp
index 7c8fe1f..ed40d25 100644
--- a/tests/extension/vibrator/aidl/default/Android.bp
+++ b/tests/extension/vibrator/aidl/default/Android.bp
@@ -20,6 +20,6 @@
"libbase",
"libbinder_ndk",
"android.hardware.vibrator-ndk_platform",
- "test-android.hardware.vibrator-ext-ndk_platform",
+ "android.hardware.tests.extension.vibrator-ndk_platform",
],
}
diff --git a/tests/lazy/1.0/.hidl_for_test b/tests/lazy/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/lazy/1.0/.hidl_for_test
diff --git a/tests/lazy/1.0/Android.bp b/tests/lazy/1.0/Android.bp
new file mode 100644
index 0000000..d2f8175
--- /dev/null
+++ b/tests/lazy/1.0/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.tests.lazy@1.0",
+ root: "android.hardware",
+ system_ext_specific: true,
+ srcs: [
+ "ILazy.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/tests/lazy/1.0/ILazy.hal b/tests/lazy/1.0/ILazy.hal
new file mode 100644
index 0000000..b0be48e
--- /dev/null
+++ b/tests/lazy/1.0/ILazy.hal
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tests.lazy@1.0;
+
+interface ILazy {};
diff --git a/tetheroffload/config/1.0/vts/functional/Android.bp b/tetheroffload/config/1.0/vts/functional/Android.bp
index 7b472e3..ad5a1b1 100644
--- a/tetheroffload/config/1.0/vts/functional/Android.bp
+++ b/tetheroffload/config/1.0/vts/functional/Android.bp
@@ -17,5 +17,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalTetheroffloadConfigV1_0TargetTest.cpp"],
static_libs: ["android.hardware.tetheroffload.config@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/tetheroffload/control/1.0/vts/functional/Android.bp b/tetheroffload/control/1.0/vts/functional/Android.bp
index 4af59b6..c51dd8b 100644
--- a/tetheroffload/control/1.0/vts/functional/Android.bp
+++ b/tetheroffload/control/1.0/vts/functional/Android.bp
@@ -20,5 +20,5 @@
"android.hardware.tetheroffload.config@1.0",
"android.hardware.tetheroffload.control@1.0",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/thermal/1.0/vts/functional/Android.bp b/thermal/1.0/vts/functional/Android.bp
index d183bd8..5ccf07a 100644
--- a/thermal/1.0/vts/functional/Android.bp
+++ b/thermal/1.0/vts/functional/Android.bp
@@ -19,6 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalThermalV1_0TargetTest.cpp"],
static_libs: ["android.hardware.thermal@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/thermal/1.1/vts/functional/Android.bp b/thermal/1.1/vts/functional/Android.bp
index 2c43d79..b869ece 100644
--- a/thermal/1.1/vts/functional/Android.bp
+++ b/thermal/1.1/vts/functional/Android.bp
@@ -22,5 +22,5 @@
"android.hardware.thermal@1.0",
"android.hardware.thermal@1.1",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/thermal/2.0/vts/functional/Android.bp b/thermal/2.0/vts/functional/Android.bp
index 0940576..026cb62 100644
--- a/thermal/2.0/vts/functional/Android.bp
+++ b/thermal/2.0/vts/functional/Android.bp
@@ -22,6 +22,6 @@
"android.hardware.thermal@1.0",
"android.hardware.thermal@2.0",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/tv/input/1.0/vts/functional/Android.bp b/tv/input/1.0/vts/functional/Android.bp
index 5d20bce..29d4e21 100644
--- a/tv/input/1.0/vts/functional/Android.bp
+++ b/tv/input/1.0/vts/functional/Android.bp
@@ -21,7 +21,7 @@
static_libs: ["android.hardware.tv.input@1.0"],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
require_root: true,
}
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index 43c4e3a..4e5ae4b 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -52,7 +52,7 @@
mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
- return startFrontendInputLoop();
+ return Result::SUCCESS;
}
Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
@@ -60,7 +60,6 @@
ALOGV("%s", __FUNCTION__);
uint32_t filterId;
-
if (!mUnusedFilterIds.empty()) {
filterId = *mUnusedFilterIds.begin();
@@ -72,7 +71,7 @@
mUsedFilterIds.insert(filterId);
if (cb == nullptr) {
- ALOGW("callback can't be null");
+ ALOGW("[Demux] callback can't be null");
_hidl_cb(Result::INVALID_ARGUMENT, new Filter());
return Void();
}
@@ -85,8 +84,12 @@
}
mFilters[filterId] = filter;
+ bool result = true;
+ if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
+ result = mDvr->addPlaybackFilter(filter);
+ }
- _hidl_cb(Result::SUCCESS, filter);
+ _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
return Void();
}
@@ -132,7 +135,7 @@
ALOGV("%s", __FUNCTION__);
if (cb == nullptr) {
- ALOGW("DVR callback can't be null");
+ ALOGW("[Demux] DVR callback can't be null");
_hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
return Void();
}
@@ -176,11 +179,11 @@
void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
set<uint32_t>::iterator it;
+ uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
+ if (DEBUG_DEMUX) {
+ ALOGW("[Demux] start ts filter pid: %d", pid);
+ }
for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
- uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
- if (DEBUG_FILTER) {
- ALOGW("start ts filter pid: %d", pid);
- }
if (pid == mFilters[*it]->getTpid()) {
mFilters[*it]->updateFilterOutput(data);
}
@@ -189,10 +192,10 @@
void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
set<uint32_t>::iterator it;
+ if (DEBUG_DEMUX) {
+ ALOGW("[Demux] update record filter output");
+ }
for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
- if (DEBUG_FILTER) {
- ALOGW("update record filter output");
- }
mFilters[*it]->updateRecordOutput(data);
}
}
@@ -234,11 +237,9 @@
return mFilters[filterId]->getTpid();
}
-Result Demux::startFrontendInputLoop() {
+void Demux::startFrontendInputLoop() {
pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
-
- return Result::SUCCESS;
}
void* Demux::__threadLoopFrontend(void* user) {
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 1405d0c..3c91daf 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -89,6 +89,7 @@
void updateFilterOutput(uint16_t filterId, vector<uint8_t> data);
uint16_t getFilterTpid(uint32_t filterId);
void setIsRecording(bool isRecording);
+ void startFrontendInputLoop();
private:
// Tuner service
@@ -104,7 +105,6 @@
uint32_t filterId;
};
- Result startFrontendInputLoop();
static void* __threadLoopFrontend(void* user);
void frontendInputThreadLoop();
@@ -188,7 +188,7 @@
int mPesSizeLeft = 0;
vector<uint8_t> mPesOutput;
- const bool DEBUG_FILTER = false;
+ const bool DEBUG_DEMUX = false;
};
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Dvr.cpp b/tv/tuner/1.0/default/Dvr.cpp
index 3088a9d..adb2635 100644
--- a/tv/tuner/1.0/default/Dvr.cpp
+++ b/tv/tuner/1.0/default/Dvr.cpp
@@ -71,13 +71,10 @@
}
// check if the attached filter is a record filter
-
mFilters[filterId] = filter;
- mIsRecordFilterAttached = true;
if (!mDemux->attachRecordFilter(filterId)) {
return Result::INVALID_ARGUMENT;
}
- mDemux->setIsRecording(mIsRecordStarted | mIsRecordFilterAttached);
return Result::SUCCESS;
}
@@ -110,7 +107,6 @@
// If all the filters are detached, record can't be started
if (mFilters.empty()) {
mIsRecordFilterAttached = false;
- mDemux->setIsRecording(mIsRecordStarted | mIsRecordFilterAttached);
}
return Result::SUCCESS;
@@ -132,8 +128,7 @@
pthread_setname_np(mDvrThread, "playback_waiting_loop");
} else if (mType == DvrType::RECORD) {
mRecordStatus = RecordStatus::DATA_READY;
- mIsRecordStarted = true;
- mDemux->setIsRecording(mIsRecordStarted | mIsRecordFilterAttached);
+ mDemux->setIsRecording(mType == DvrType::RECORD);
}
// TODO start another thread to send filter status callback to the framework
@@ -149,7 +144,7 @@
std::lock_guard<std::mutex> lock(mDvrThreadLock);
mIsRecordStarted = false;
- mDemux->setIsRecording(mIsRecordStarted | mIsRecordFilterAttached);
+ mDemux->setIsRecording(false);
return Result::SUCCESS;
}
@@ -175,7 +170,7 @@
std::unique_ptr<DvrMQ> tmpDvrMQ =
std::unique_ptr<DvrMQ>(new (std::nothrow) DvrMQ(mBufferSize, true));
if (!tmpDvrMQ->isValid()) {
- ALOGW("Failed to create FMQ of DVR");
+ ALOGW("[Dvr] Failed to create FMQ of DVR");
return false;
}
@@ -256,7 +251,6 @@
int playbackPacketSize = mDvrSettings.playback().packetSize;
vector<uint8_t> dataOutputBuffer;
dataOutputBuffer.resize(playbackPacketSize);
-
// Dispatch the packet to the PID matching filter output buffer
for (int i = 0; i < size / playbackPacketSize; i++) {
if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) {
@@ -283,7 +277,6 @@
bool Dvr::startFilterDispatcher() {
std::map<uint32_t, sp<IFilter>>::iterator it;
-
// Handle the output data per filter type
for (it = mFilters.begin(); it != mFilters.end(); it++) {
if (mDemux->startFilterHandler(it->first) != Result::SUCCESS) {
@@ -296,7 +289,10 @@
bool Dvr::writeRecordFMQ(const std::vector<uint8_t>& data) {
std::lock_guard<std::mutex> lock(mWriteLock);
- ALOGW("[Dvr] write record FMQ");
+ if (mRecordStatus == RecordStatus::OVERFLOW) {
+ ALOGW("[Dvr] stops writing and wait for the client side flushing.");
+ return true;
+ }
if (mDvrMQ->write(data.data(), data.size())) {
mDvrEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
maySendRecordStatusCallback();
@@ -333,6 +329,27 @@
return mRecordStatus;
}
+bool Dvr::addPlaybackFilter(sp<IFilter> filter) {
+ uint32_t filterId;
+ Result status;
+
+ filter->getId([&](Result result, uint32_t id) {
+ filterId = id;
+ status = result;
+ });
+
+ if (status != Result::SUCCESS) {
+ return false;
+ }
+
+ mFilters[filterId] = filter;
+ return true;
+}
+
+DvrType Dvr::getType() {
+ return mType;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Dvr.h b/tv/tuner/1.0/default/Dvr.h
index f39d8db..08afd5d 100644
--- a/tv/tuner/1.0/default/Dvr.h
+++ b/tv/tuner/1.0/default/Dvr.h
@@ -81,6 +81,8 @@
bool createDvrMQ();
void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer);
bool writeRecordFMQ(const std::vector<uint8_t>& data);
+ DvrType getType();
+ bool addPlaybackFilter(sp<IFilter> filter);
private:
// Demux service
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index f610c60..fef7a35 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -73,18 +73,22 @@
switch (mType.mainType) {
case DemuxFilterMainType::TS:
mTpid = settings.ts().tpid;
+ if (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+ mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+ mIsMediaFilter = true;
+ }
break;
case DemuxFilterMainType::MMTP:
- /*mmtpSettings*/
+ if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+ mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+ mIsMediaFilter = true;
+ }
break;
case DemuxFilterMainType::IP:
- /*ipSettings*/
break;
case DemuxFilterMainType::TLV:
- /*tlvSettings*/
break;
case DemuxFilterMainType::ALP:
- /*alpSettings*/
break;
default:
break;
@@ -145,7 +149,7 @@
std::unique_ptr<FilterMQ> tmpFilterMQ =
std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(mBufferSize, true));
if (!tmpFilterMQ->isValid()) {
- ALOGW("Failed to create FMQ of filter with id: %d", mFilterId);
+ ALOGW("[Filter] Failed to create FMQ of filter with id: %d", mFilterId);
return false;
}
@@ -241,9 +245,7 @@
}
void Filter::freeAvHandle() {
- if (mType.mainType != DemuxFilterMainType::TS ||
- (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO &&
- mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO)) {
+ if (!mIsMediaFilter) {
return;
}
for (int i = 0; i < mFilterEvent.events.size(); i++) {
@@ -288,13 +290,11 @@
void Filter::updateFilterOutput(vector<uint8_t> data) {
std::lock_guard<std::mutex> lock(mFilterOutputLock);
- ALOGD("[Filter] filter output updated");
mFilterOutput.insert(mFilterOutput.end(), data.begin(), data.end());
}
void Filter::updateRecordOutput(vector<uint8_t> data) {
std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
- ALOGD("[Filter] record filter output updated");
mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end());
}
@@ -436,7 +436,6 @@
if (mFilterOutput.empty()) {
return Result::SUCCESS;
}
-
for (int i = 0; i < mFilterOutput.size(); i += 188) {
if (mPesSizeLeft == 0) {
uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index afed98e..9b49ad8 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -103,6 +103,7 @@
uint32_t mFilterId;
uint32_t mBufferSize;
DemuxFilterType mType;
+ bool mIsMediaFilter = false;
DemuxFilterSettings mFilterSettings;
uint16_t mTpid;
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index bb0d8dc..b509599 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -41,6 +41,7 @@
ALOGV("%s", __FUNCTION__);
// Reset callback
mCallback = nullptr;
+ mIsLocked = false;
return Result::SUCCESS;
}
@@ -63,7 +64,9 @@
return Result::INVALID_STATE;
}
+ mTunerService->frontendStartTune(mId);
mCallback->onEvent(FrontendEventType::LOCKED);
+ mIsLocked = false;
return Result::SUCCESS;
}
@@ -71,16 +74,42 @@
ALOGV("%s", __FUNCTION__);
mTunerService->frontendStopTune(mId);
+ mIsLocked = false;
return Result::SUCCESS;
}
-Return<Result> Frontend::scan(const FrontendSettings& /* settings */, FrontendScanType /* type */) {
+Return<Result> Frontend::scan(const FrontendSettings& settings, FrontendScanType type) {
ALOGV("%s", __FUNCTION__);
+ if (mType == FrontendType::ATSC) {
+ FrontendScanMessage msg;
+ msg.isLocked(true);
+ mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
+ mIsLocked = true;
+ return Result::SUCCESS;
+ }
+ if (mType != FrontendType::DVBT) {
+ return Result::UNAVAILABLE;
+ }
+
FrontendScanMessage msg;
+
+ if (mIsLocked) {
+ msg.isEnd(true);
+ mCallback->onScanMessage(FrontendScanMessageType::END, msg);
+ return Result::SUCCESS;
+ }
+
+ uint32_t frequency = settings.dvbt().frequency;
+ if (type == FrontendScanType::SCAN_BLIND) {
+ frequency += 100;
+ }
+ msg.frequencies({frequency});
+ mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg);
msg.isLocked(true);
mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
+ mIsLocked = true;
return Result::SUCCESS;
}
@@ -88,6 +117,7 @@
Return<Result> Frontend::stopScan() {
ALOGV("%s", __FUNCTION__);
+ mIsLocked = false;
return Result::SUCCESS;
}
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
index b954639..65537d7 100644
--- a/tv/tuner/1.0/default/Frontend.h
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -74,8 +74,9 @@
sp<Tuner> mTunerService;
FrontendType mType = FrontendType::UNDEFINED;
FrontendId mId = 0;
+ bool mIsLocked = false;
- const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts";
+ const string FRONTEND_STREAM_FILE = "/vendor/etc/segment000000.ts";
std::ifstream mFrontendData;
};
diff --git a/tv/tuner/1.0/default/Lnb.cpp b/tv/tuner/1.0/default/Lnb.cpp
index 51931d6..6025339 100644
--- a/tv/tuner/1.0/default/Lnb.cpp
+++ b/tv/tuner/1.0/default/Lnb.cpp
@@ -27,6 +27,9 @@
namespace implementation {
Lnb::Lnb() {}
+Lnb::Lnb(int id) {
+ mId = id;
+}
Lnb::~Lnb() {}
@@ -66,9 +69,13 @@
return Result::SUCCESS;
}
+int Lnb::getId() {
+ return mId;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace tuner
} // namespace tv
} // namespace hardware
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/tv/tuner/1.0/default/Lnb.h b/tv/tuner/1.0/default/Lnb.h
index f285cb9..1e97214 100644
--- a/tv/tuner/1.0/default/Lnb.h
+++ b/tv/tuner/1.0/default/Lnb.h
@@ -38,6 +38,7 @@
class Lnb : public ILnb {
public:
Lnb();
+ Lnb(int id);
virtual Return<Result> setCallback(const sp<ILnbCallback>& callback) override;
@@ -51,7 +52,10 @@
virtual Return<Result> close() override;
+ int getId();
+
private:
+ int mId;
virtual ~Lnb();
};
@@ -62,4 +66,4 @@
} // namespace hardware
} // namespace android
-#endif // ANDROID_HARDWARE_TV_TUNER_V1_0_LNB_H_
\ No newline at end of file
+#endif // ANDROID_HARDWARE_TV_TUNER_V1_0_LNB_H_
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index 8fb5061..b1f2490 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -46,6 +46,52 @@
mFrontends[5] = new Frontend(FrontendType::ISDBT, 5, this);
mFrontends[6] = new Frontend(FrontendType::ANALOG, 6, this);
mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this);
+
+ FrontendInfo::FrontendCapabilities caps;
+ mFrontendCaps.resize(mFrontendSize);
+ caps = FrontendInfo::FrontendCapabilities();
+ caps.dvbtCaps(FrontendDvbtCapabilities());
+ mFrontendCaps[0] = caps;
+
+ caps = FrontendInfo::FrontendCapabilities();
+ caps.atscCaps(FrontendAtscCapabilities());
+ mFrontendCaps[1] = caps;
+
+ caps = FrontendInfo::FrontendCapabilities();
+ caps.dvbcCaps(FrontendDvbcCapabilities());
+ mFrontendCaps[2] = caps;
+
+ caps = FrontendInfo::FrontendCapabilities();
+ caps.dvbsCaps(FrontendDvbsCapabilities());
+ mFrontendCaps[3] = caps;
+
+ caps = FrontendInfo::FrontendCapabilities();
+ caps.dvbtCaps(FrontendDvbtCapabilities());
+ mFrontendCaps[4] = caps;
+
+ caps = FrontendInfo::FrontendCapabilities();
+ FrontendIsdbtCapabilities isdbtCaps{
+ .modeCap = FrontendIsdbtMode::MODE_1 | FrontendIsdbtMode::MODE_2,
+ .bandwidthCap = (unsigned int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
+ .modulationCap = (unsigned int)FrontendIsdbtModulation::MOD_16QAM,
+ // ISDBT shares coderate and guard interval with DVBT
+ .coderateCap = FrontendDvbtCoderate::CODERATE_4_5 | FrontendDvbtCoderate::CODERATE_6_7,
+ .guardIntervalCap = (unsigned int)FrontendDvbtGuardInterval::INTERVAL_1_128,
+ };
+ caps.isdbtCaps(isdbtCaps);
+ mFrontendCaps[5] = caps;
+
+ caps = FrontendInfo::FrontendCapabilities();
+ caps.analogCaps(FrontendAnalogCapabilities());
+ mFrontendCaps[6] = caps;
+
+ caps = FrontendInfo::FrontendCapabilities();
+ caps.atscCaps(FrontendAtscCapabilities());
+ mFrontendCaps[7] = caps;
+
+ mLnbs.resize(2);
+ mLnbs[0] = new Lnb(0);
+ mLnbs[1] = new Lnb(1);
}
Tuner::~Tuner() {}
@@ -106,40 +152,43 @@
return Void();
}
-Return<void> Tuner::getFrontendInfo(FrontendId /*frontendId*/, getFrontendInfo_cb _hidl_cb) {
+Return<void> Tuner::getFrontendInfo(FrontendId frontendId, getFrontendInfo_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
- vector<FrontendStatusType> statusCaps = {
- FrontendStatusType::DEMOD_LOCK,
- FrontendStatusType::SNR,
- FrontendStatusType::FEC,
- FrontendStatusType::MODULATION,
- FrontendStatusType::PLP_ID,
- FrontendStatusType::LAYER_ERROR,
- FrontendStatusType::ATSC3_PLP_INFO,
- };
- FrontendInfo::FrontendCapabilities frontendCaps;
- FrontendIsdbtCapabilities isdbtCaps{
- .modeCap = FrontendIsdbtMode::MODE_1 | FrontendIsdbtMode::MODE_2,
- .bandwidthCap = (unsigned int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
- .modulationCap = (unsigned int)FrontendIsdbtModulation::MOD_16QAM,
- // ISDBT shares coderate and guard interval with DVBT
- .coderateCap = FrontendDvbtCoderate::CODERATE_4_5 | FrontendDvbtCoderate::CODERATE_6_7,
- .guardIntervalCap = (unsigned int)FrontendDvbtGuardInterval::INTERVAL_1_128,
- };
- frontendCaps.isdbtCaps(isdbtCaps);
- // assign randomly selected values for testing.
- FrontendInfo info{
- .type = FrontendType::ISDBT,
- .minFrequency = 139,
- .maxFrequency = 1139,
- .minSymbolRate = 45,
- .maxSymbolRate = 1145,
- .acquireRange = 30,
- .exclusiveGroupId = 57,
- .statusCaps = statusCaps,
- .frontendCaps = frontendCaps,
- };
+ FrontendInfo info;
+ if (frontendId >= mFrontendSize) {
+ _hidl_cb(Result::INVALID_ARGUMENT, info);
+ return Void();
+ }
+
+ switch (mFrontends[frontendId]->getFrontendType()) {
+ case FrontendType::DVBT:
+ info.type = FrontendType::DVBT;
+ break;
+ default:
+ vector<FrontendStatusType> statusCaps = {
+ FrontendStatusType::DEMOD_LOCK,
+ FrontendStatusType::SNR,
+ FrontendStatusType::FEC,
+ FrontendStatusType::MODULATION,
+ FrontendStatusType::PLP_ID,
+ FrontendStatusType::LAYER_ERROR,
+ FrontendStatusType::ATSC3_PLP_INFO,
+ };
+ // assign randomly selected values for testing.
+ info = {
+ .type = mFrontends[frontendId]->getFrontendType(),
+ .minFrequency = 139,
+ .maxFrequency = 1139,
+ .minSymbolRate = 45,
+ .maxSymbolRate = 1145,
+ .acquireRange = 30,
+ .exclusiveGroupId = 57,
+ .statusCaps = statusCaps,
+ .frontendCaps = mFrontendCaps[frontendId],
+ };
+ break;
+ }
_hidl_cb(Result::SUCCESS, info);
return Void();
@@ -149,17 +198,24 @@
ALOGV("%s", __FUNCTION__);
vector<LnbId> lnbIds;
+ lnbIds.resize(mLnbs.size());
+ for (int i = 0; i < lnbIds.size(); i++) {
+ lnbIds[i] = mLnbs[i]->getId();
+ }
_hidl_cb(Result::SUCCESS, lnbIds);
return Void();
}
-Return<void> Tuner::openLnbById(LnbId /* lnbId */, openLnbById_cb _hidl_cb) {
+Return<void> Tuner::openLnbById(LnbId lnbId, openLnbById_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
- sp<ILnb> lnb = new Lnb();
+ if (lnbId >= mLnbs.size()) {
+ _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
+ return Void();
+ }
- _hidl_cb(Result::SUCCESS, lnb);
+ _hidl_cb(Result::SUCCESS, mLnbs[lnbId]);
return Void();
}
@@ -191,6 +247,15 @@
}
}
+void Tuner::frontendStartTune(uint32_t frontendId) {
+ map<uint32_t, uint32_t>::iterator it = mFrontendToDemux.find(frontendId);
+ uint32_t demuxId;
+ if (it != mFrontendToDemux.end()) {
+ demuxId = it->second;
+ mDemuxes[demuxId]->startFrontendInputLoop();
+ }
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h
index 7a8a919..5de568f 100644
--- a/tv/tuner/1.0/default/Tuner.h
+++ b/tv/tuner/1.0/default/Tuner.h
@@ -21,6 +21,7 @@
#include <map>
#include "Demux.h"
#include "Frontend.h"
+#include "Lnb.h"
using namespace std;
@@ -62,12 +63,14 @@
void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId);
+ void frontendStartTune(uint32_t frontendId);
void frontendStopTune(uint32_t frontendId);
private:
virtual ~Tuner();
// Static mFrontends array to maintain local frontends information
vector<sp<Frontend>> mFrontends;
+ vector<FrontendInfo::FrontendCapabilities> mFrontendCaps;
std::map<uint32_t, uint32_t> mFrontendToDemux;
std::map<uint32_t, sp<Demux>> mDemuxes;
// To maintain how many Frontends we have
@@ -75,6 +78,7 @@
// The last used demux id. Initial value is -1.
// First used id will be 0.
int mLastUsedId = -1;
+ vector<sp<Lnb>> mLnbs;
};
} // namespace implementation
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 3637708..b152a29 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -17,7 +17,13 @@
cc_test {
name: "VtsHalTvTunerV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
- srcs: ["VtsHalTvTunerV1_0TargetTest.cpp"],
+ srcs: [
+ "VtsHalTvTunerV1_0TargetTest.cpp",
+ "FrontendTests.cpp",
+ "DemuxTests.cpp",
+ "FilterTests.cpp",
+ "DvrTests.cpp",
+ ],
static_libs: [
"android.hardware.tv.tuner@1.0",
"android.hidl.allocator@1.0",
@@ -32,7 +38,7 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
require_root: true,
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.cpp b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
new file mode 100644
index 0000000..b1d8a0a
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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 "DemuxTests.h"
+
+AssertionResult DemuxTests::openDemux(sp<IDemux>& demux, uint32_t& demuxId) {
+ Result status;
+ mService->openDemux([&](Result result, uint32_t id, const sp<IDemux>& demuxSp) {
+ mDemux = demuxSp;
+ demux = demuxSp;
+ demuxId = id;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DemuxTests::setDemuxFrontendDataSource(uint32_t frontendId) {
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ auto status = mDemux->setFrontendDataSource(frontendId);
+ return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::closeDemux() {
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ auto status = mDemux->close();
+ mDemux = nullptr;
+ return AssertionResult(status.isOk());
+}
\ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.h b/tv/tuner/1.0/vts/functional/DemuxTests.h
new file mode 100644
index 0000000..6e1e395
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -0,0 +1,54 @@
+/*
+ * 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/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <gtest/gtest.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::sp;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+class DemuxTests {
+ public:
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+
+ AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
+ AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
+ AssertionResult closeDemux();
+
+ protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+ sp<ITuner> mService;
+ sp<IDemux> mDemux;
+};
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp
new file mode 100644
index 0000000..7e7f8e6
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp
@@ -0,0 +1,265 @@
+/*
+ * 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 "DvrTests.h"
+
+void DvrCallback::startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings,
+ MQDesc& playbackMQDescriptor) {
+ mInputDataFile = dataInputFile;
+ mPlaybackSettings = settings;
+ mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
+ EXPECT_TRUE(mPlaybackMQ);
+ pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, this);
+ pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
+}
+
+void DvrCallback::stopPlaybackThread() {
+ mPlaybackThreadRunning = false;
+ mKeepWritingPlaybackFMQ = false;
+
+ android::Mutex::Autolock autoLock(mPlaybackThreadLock);
+}
+
+void* DvrCallback::__threadLoopPlayback(void* user) {
+ DvrCallback* const self = static_cast<DvrCallback*>(user);
+ self->playbackThreadLoop();
+ return 0;
+}
+
+void DvrCallback::playbackThreadLoop() {
+ android::Mutex::Autolock autoLock(mPlaybackThreadLock);
+ mPlaybackThreadRunning = true;
+
+ // Create the EventFlag that is used to signal the HAL impl that data have been
+ // written into the Playback FMQ
+ EventFlag* playbackMQEventFlag;
+ EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
+ android::OK);
+
+ // open the stream and get its length
+ std::ifstream inputData(mInputDataFile.c_str(), std::ifstream::binary);
+ int writeSize = mPlaybackSettings.packetSize * 6;
+ char* buffer = new char[writeSize];
+ ALOGW("[vts] playback thread loop start %s!", mInputDataFile.c_str());
+ if (!inputData.is_open()) {
+ mPlaybackThreadRunning = false;
+ ALOGW("[vts] Error %s", strerror(errno));
+ }
+
+ while (mPlaybackThreadRunning) {
+ // move the stream pointer for packet size * 6 every read until the end
+ while (mKeepWritingPlaybackFMQ) {
+ inputData.read(buffer, writeSize);
+ if (!inputData) {
+ int leftSize = inputData.gcount();
+ if (leftSize == 0) {
+ mPlaybackThreadRunning = false;
+ break;
+ }
+ inputData.clear();
+ inputData.read(buffer, leftSize);
+ // Write the left over of the input data and quit the thread
+ if (leftSize > 0) {
+ EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
+ playbackMQEventFlag->wake(
+ static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+ }
+ mPlaybackThreadRunning = false;
+ break;
+ }
+ // Write input FMQ and notify the Tuner Implementation
+ EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
+ playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+ inputData.seekg(writeSize, inputData.cur);
+ sleep(1);
+ }
+ }
+
+ ALOGW("[vts] Playback thread end.");
+
+ delete[] buffer;
+ inputData.close();
+}
+
+void DvrCallback::testRecordOutput() {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (mDataOutputBuffer.empty()) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
+ stopRecordThread();
+ return;
+ }
+ }
+ stopRecordThread();
+ ALOGW("[vts] record pass and stop");
+}
+
+void DvrCallback::startRecordOutputThread(RecordSettings recordSettings,
+ MQDesc& recordMQDescriptor) {
+ mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
+ EXPECT_TRUE(mRecordMQ);
+ struct RecordThreadArgs* threadArgs =
+ (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
+ threadArgs->user = this;
+ threadArgs->recordSettings = &recordSettings;
+ threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
+
+ pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
+ pthread_setname_np(mRecordThread, "test_record_input_loop");
+}
+
+void* DvrCallback::__threadLoopRecord(void* threadArgs) {
+ DvrCallback* const self =
+ static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
+ self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings,
+ ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
+ return 0;
+}
+
+void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) {
+ ALOGD("[vts] DvrCallback record threadLoop start.");
+ android::Mutex::Autolock autoLock(mRecordThreadLock);
+ mRecordThreadRunning = true;
+ mKeepReadingRecordFMQ = true;
+
+ // Create the EventFlag that is used to signal the HAL impl that data have been
+ // read from the Record FMQ
+ EventFlag* recordMQEventFlag;
+ EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
+ android::OK);
+
+ while (mRecordThreadRunning) {
+ while (*keepReadingRecordFMQ) {
+ uint32_t efState = 0;
+ android::status_t status = recordMQEventFlag->wait(
+ static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
+ true /* retry on spurious wake */);
+ if (status != android::OK) {
+ ALOGD("[vts] wait for data ready on the record FMQ");
+ continue;
+ }
+ // Our current implementation filter the data and write it into the filter FMQ
+ // immediately after the DATA_READY from the VTS/framework
+ if (!readRecordFMQ()) {
+ ALOGD("[vts] record data failed to be filtered. Ending thread");
+ mRecordThreadRunning = false;
+ break;
+ }
+ }
+ }
+
+ mRecordThreadRunning = false;
+ ALOGD("[vts] record thread ended.");
+}
+
+bool DvrCallback::readRecordFMQ() {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ bool result = false;
+ mDataOutputBuffer.clear();
+ mDataOutputBuffer.resize(mRecordMQ->availableToRead());
+ result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
+ EXPECT_TRUE(result) << "can't read from Record MQ";
+ mMsgCondition.signal();
+ return result;
+}
+
+void DvrCallback::stopRecordThread() {
+ mKeepReadingRecordFMQ = false;
+ mRecordThreadRunning = false;
+}
+
+AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+ // Create dvr callback
+ mDvrCallback = new DvrCallback();
+
+ mDemux->openDvr(type, bufferSize, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
+ mDvr = dvr;
+ status = result;
+ });
+
+ if (status == Result::SUCCESS) {
+ mDvrCallback->setDvr(mDvr);
+ }
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvr(DvrSettings setting) {
+ Result status = mDvr->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::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);
+}
+
+AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+
+ status = mDvr->attachFilter(filter);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+
+ status = mDvr->detachFilter(filter);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::startDvr() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+
+ status = mDvr->start();
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::stopDvr() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+
+ status = mDvr->stop();
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+void DvrTests::closeDvr() {
+ ASSERT_TRUE(mDemux);
+ ASSERT_TRUE(mDvr);
+ ASSERT_TRUE(mDvr->close() == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.h b/tv/tuner/1.0/vts/functional/DvrTests.h
new file mode 100644
index 0000000..dd00c27
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DvrTests.h
@@ -0,0 +1,185 @@
+/*
+ * 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 <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.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/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/Status.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+
+#include "FilterTests.h"
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DvrSettings;
+using android::hardware::tv::tuner::V1_0::DvrType;
+using android::hardware::tv::tuner::V1_0::IDvr;
+using android::hardware::tv::tuner::V1_0::IDvrCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::PlaybackSettings;
+using android::hardware::tv::tuner::V1_0::PlaybackStatus;
+using android::hardware::tv::tuner::V1_0::RecordSettings;
+using android::hardware::tv::tuner::V1_0::RecordStatus;
+using android::hardware::tv::tuner::V1_0::Result;
+
+#define WAIT_TIMEOUT 3000000000
+
+class DvrCallback : public IDvrCallback {
+ public:
+ virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
+ ALOGD("[vts] record status %hhu", status);
+ switch (status) {
+ case DemuxFilterStatus::DATA_READY:
+ break;
+ case DemuxFilterStatus::LOW_WATER:
+ break;
+ case DemuxFilterStatus::HIGH_WATER:
+ case DemuxFilterStatus::OVERFLOW:
+ ALOGD("[vts] record overflow. Flushing.");
+ EXPECT_TRUE(mDvr) << "Dvr callback is not set with an IDvr";
+ if (mDvr) {
+ Result result = mDvr->flush();
+ ALOGD("[vts] Flushing result %d.", result);
+ }
+ break;
+ }
+ return Void();
+ }
+
+ virtual Return<void> onPlaybackStatus(PlaybackStatus status) override {
+ // android::Mutex::Autolock autoLock(mMsgLock);
+ ALOGD("[vts] playback status %d", status);
+ switch (status) {
+ case PlaybackStatus::SPACE_EMPTY:
+ case PlaybackStatus::SPACE_ALMOST_EMPTY:
+ ALOGD("[vts] keep playback inputing %d", status);
+ mKeepWritingPlaybackFMQ = true;
+ break;
+ case PlaybackStatus::SPACE_ALMOST_FULL:
+ case PlaybackStatus::SPACE_FULL:
+ ALOGD("[vts] stop playback inputing %d", status);
+ mKeepWritingPlaybackFMQ = false;
+ break;
+ }
+ return Void();
+ }
+
+ void stopPlaybackThread();
+ void testRecordOutput();
+ void stopRecordThread();
+
+ void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings,
+ MQDesc& playbackMQDescriptor);
+ void startRecordOutputThread(RecordSettings recordSettings, MQDesc& recordMQDescriptor);
+ static void* __threadLoopPlayback(void* user);
+ static void* __threadLoopRecord(void* threadArgs);
+ void playbackThreadLoop();
+ void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
+
+ bool readRecordFMQ();
+
+ void setDvr(sp<IDvr> dvr) { mDvr = dvr; }
+
+ private:
+ struct RecordThreadArgs {
+ DvrCallback* user;
+ RecordSettings* recordSettings;
+ bool* keepReadingRecordFMQ;
+ };
+ // uint16_t mDataLength = 0;
+ std::vector<uint8_t> mDataOutputBuffer;
+
+ std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
+ std::unique_ptr<FilterMQ> mPlaybackMQ;
+ std::unique_ptr<FilterMQ> mRecordMQ;
+ std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
+
+ android::Mutex mMsgLock;
+ android::Mutex mPlaybackThreadLock;
+ android::Mutex mRecordThreadLock;
+ android::Condition mMsgCondition;
+
+ bool mKeepWritingPlaybackFMQ = true;
+ bool mKeepReadingRecordFMQ = true;
+ bool mPlaybackThreadRunning;
+ bool mRecordThreadRunning;
+ pthread_t mPlaybackThread;
+ pthread_t mRecordThread;
+ string mInputDataFile;
+ PlaybackSettings mPlaybackSettings;
+
+ sp<IDvr> mDvr = nullptr;
+
+ // int mPidFilterOutputCount = 0;
+};
+
+class DvrTests {
+ public:
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+ void setDemux(sp<IDemux> demux) { mDemux = demux; }
+
+ void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) {
+ mDvrCallback->startPlaybackInputThread(dataInputFile, settings, mDvrMQDescriptor);
+ };
+
+ void startRecordOutputThread(RecordSettings settings) {
+ mDvrCallback->startRecordOutputThread(settings, mDvrMQDescriptor);
+ };
+
+ void stopPlaybackThread() { mDvrCallback->stopPlaybackThread(); }
+ void testRecordOutput() { mDvrCallback->testRecordOutput(); }
+ void stopRecordThread() { mDvrCallback->stopPlaybackThread(); }
+
+ AssertionResult openDvrInDemux(DvrType type, uint32_t bufferSize);
+ AssertionResult configDvr(DvrSettings setting);
+ AssertionResult getDvrMQDescriptor();
+ AssertionResult attachFilterToDvr(sp<IFilter> filter);
+ AssertionResult detachFilterToDvr(sp<IFilter> filter);
+ AssertionResult stopDvr();
+ AssertionResult startDvr();
+ void closeDvr();
+
+ protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+ sp<ITuner> mService;
+ sp<IDvr> mDvr;
+ sp<IDemux> mDemux;
+ sp<DvrCallback> mDvrCallback;
+ MQDesc mDvrMQDescriptor;
+
+ pthread_t mPlaybackshread;
+ bool mPlaybackThreadRunning;
+};
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
new file mode 100644
index 0000000..4639e59
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -0,0 +1,226 @@
+/*
+ * 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 "FilterTests.h"
+
+void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
+ struct FilterThreadArgs* threadArgs =
+ (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
+ threadArgs->user = this;
+ threadArgs->event = event;
+
+ pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
+ pthread_setname_np(mFilterThread, "test_playback_input_loop");
+}
+
+void FilterCallback::testFilterDataOutput() {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (mPidFilterOutputCount < 1) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
+ return;
+ }
+ }
+ mPidFilterOutputCount = 0;
+ ALOGW("[vts] pass and stop");
+}
+
+void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
+ 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) {
+ mFilterIdToGoldenOutput = goldenOutputFile;
+}
+
+void* FilterCallback::__threadLoopFilter(void* threadArgs) {
+ FilterCallback* const self =
+ static_cast<FilterCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
+ self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
+ return 0;
+}
+
+void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
+ android::Mutex::Autolock autoLock(mFilterOutputLock);
+ // Read from mFilterMQ[event.filterId] per event and filter type
+
+ // Assemble to filterOutput[filterId]
+
+ // check if filterOutput[filterId] matches goldenOutput[filterId]
+
+ // If match, remove filterId entry from MQ map
+
+ // end thread
+}
+
+bool FilterCallback::readFilterEventData() {
+ bool result = false;
+ DemuxFilterEvent filterEvent = mFilterEvent;
+ ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
+ // todo separate filter handlers
+ for (int i = 0; i < filterEvent.events.size(); i++) {
+ switch (mFilterEventType) {
+ case FilterEventType::SECTION:
+ mDataLength = filterEvent.events[i].section().dataLength;
+ break;
+ case FilterEventType::PES:
+ mDataLength = filterEvent.events[i].pes().dataLength;
+ break;
+ case FilterEventType::MEDIA:
+ return dumpAvData(filterEvent.events[i].media());
+ case FilterEventType::RECORD:
+ break;
+ case FilterEventType::MMTPRECORD:
+ break;
+ case FilterEventType::DOWNLOAD:
+ break;
+ default:
+ break;
+ }
+ // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
+ // match";
+
+ mDataOutputBuffer.resize(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";
+ }*/
+ }
+ mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ return result;
+}
+
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+ uint32_t length = event.dataLength;
+ uint64_t dataId = event.avDataId;
+ // read data from buffer pointed by a handle
+ hidl_handle handle = event.avMemory;
+
+ int av_fd = handle.getNativeHandle()->data[0];
+ uint8_t* buffer = static_cast<uint8_t*>(
+ mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0 /*offset*/));
+ if (buffer == MAP_FAILED) {
+ ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
+ return false;
+ }
+ uint8_t output[length + 1];
+ memcpy(output, buffer, length);
+ // print buffer and check with golden output.
+ EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
+ return true;
+}
+
+AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+ // Create demux callback
+ mFilterCallback = new FilterCallback();
+
+ // Add filter to the local demux
+ mDemux->openFilter(type, bufferSize, mFilterCallback,
+ [&](Result result, const sp<IFilter>& filter) {
+ mFilter = filter;
+ status = result;
+ });
+
+ if (status == Result::SUCCESS) {
+ mFilterCallback->setFilterEventType(getFilterEventType(type));
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::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) {
+ mFilterCallback->setFilterId(mFilterId);
+ mFilterCallback->setFilterInterface(mFilter);
+ mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
+ mFilters[mFilterId] = mFilter;
+ mFilterCallbacks[mFilterId] = mFilterCallback;
+ filterId = mFilterId;
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::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 FilterTests::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 FilterTests::startFilter(uint32_t filterId) {
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ Result status = mFilters[filterId]->start();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::stopFilter(uint32_t filterId) {
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ Result status = mFilters[filterId]->stop();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::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);
+}
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
new file mode 100644
index 0000000..71efce4
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -0,0 +1,224 @@
+/*
+ * 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/IFilter.h>
+#include <android/hardware/tv/tuner/1.0/IFilterCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
+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::DemuxTsFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IFilter;
+using android::hardware::tv::tuner::V1_0::IFilterCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+enum FilterEventType : uint8_t {
+ UNDEFINED,
+ SECTION,
+ MEDIA,
+ PES,
+ RECORD,
+ MMTPRECORD,
+ DOWNLOAD,
+ TEMI,
+};
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using MQDesc = MQDescriptorSync<uint8_t>;
+
+#define WAIT_TIMEOUT 3000000000
+
+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
+ mFilterEvent = filterEvent;
+ readFilterEventData();
+ mPidFilterOutputCount++;
+ // mFilterIdToMQ.erase(filterEvent.filterId);
+
+ // startFilterEventThread(filterEvent);
+ mMsgCondition.signal();
+ return Void();
+ }
+
+ virtual Return<void> onFilterStatus(const DemuxFilterStatus /*status*/) override {
+ return Void();
+ }
+
+ void setFilterId(uint32_t filterId) { mFilterId = filterId; }
+ void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
+ void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
+
+ void testFilterDataOutput();
+
+ void startFilterEventThread(DemuxFilterEvent event);
+ static void* __threadLoopFilter(void* threadArgs);
+ void filterThreadLoop(DemuxFilterEvent& event);
+
+ void updateFilterMQ(MQDesc& filterMQDescriptor);
+ void updateGoldenOutputMap(string goldenOutputFile);
+ bool readFilterEventData();
+ bool dumpAvData(DemuxFilterMediaEvent event);
+
+ private:
+ struct FilterThreadArgs {
+ FilterCallback* user;
+ DemuxFilterEvent event;
+ };
+ uint16_t mDataLength = 0;
+ std::vector<uint8_t> mDataOutputBuffer;
+
+ string mFilterIdToGoldenOutput;
+
+ uint32_t mFilterId;
+ sp<IFilter> mFilter;
+ FilterEventType mFilterEventType;
+ std::unique_ptr<FilterMQ> mFilterMQ;
+ EventFlag* mFilterMQEventFlag;
+ DemuxFilterEvent mFilterEvent;
+
+ android::Mutex mMsgLock;
+ android::Mutex mFilterOutputLock;
+ android::Condition mMsgCondition;
+ android::Condition mFilterOutputCondition;
+
+ pthread_t mFilterThread;
+
+ int mPidFilterOutputCount = 0;
+};
+
+class FilterTests {
+ public:
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+ void setDemux(sp<IDemux> demux) { mDemux = demux; }
+ sp<IFilter> getFilterById(uint32_t filterId) { return mFilters[filterId]; }
+
+ std::map<uint32_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
+
+ AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize);
+ 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);
+
+ FilterEventType getFilterEventType(DemuxFilterType type) {
+ FilterEventType eventType = FilterEventType::UNDEFINED;
+ switch (type.mainType) {
+ case DemuxFilterMainType::TS:
+ switch (type.subType.tsFilterType()) {
+ case DemuxTsFilterType::UNDEFINED:
+ break;
+ case DemuxTsFilterType::SECTION:
+ eventType = FilterEventType::SECTION;
+ break;
+ case DemuxTsFilterType::PES:
+ eventType = FilterEventType::PES;
+ break;
+ case DemuxTsFilterType::TS:
+ break;
+ case DemuxTsFilterType::AUDIO:
+ case DemuxTsFilterType::VIDEO:
+ eventType = FilterEventType::MEDIA;
+ break;
+ case DemuxTsFilterType::PCR:
+ break;
+ case DemuxTsFilterType::RECORD:
+ eventType = FilterEventType::RECORD;
+ break;
+ case DemuxTsFilterType::TEMI:
+ eventType = FilterEventType::TEMI;
+ break;
+ }
+ break;
+ case DemuxFilterMainType::MMTP:
+ /*mmtpSettings*/
+ break;
+ case DemuxFilterMainType::IP:
+ /*ipSettings*/
+ break;
+ case DemuxFilterMainType::TLV:
+ /*tlvSettings*/
+ break;
+ case DemuxFilterMainType::ALP:
+ /*alpSettings*/
+ break;
+ default:
+ break;
+ }
+ return eventType;
+ }
+
+ protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+ sp<ITuner> mService;
+ sp<IFilter> mFilter;
+ sp<IDemux> mDemux;
+ std::map<uint32_t, sp<IFilter>> mFilters;
+ std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
+
+ sp<FilterCallback> mFilterCallback;
+ MQDesc mFilterMQDescriptor;
+ vector<uint32_t> mUsedFilterIds;
+
+ uint32_t mFilterId = -1;
+};
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
new file mode 100644
index 0000000..fc5071c
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -0,0 +1,310 @@
+/*
+ * 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 "FrontendTests.h"
+
+Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
+ mEventReceived = true;
+ mMsgCondition.signal();
+ switch (frontendEventType) {
+ case FrontendEventType::LOCKED:
+ mLockMsgReceived = true;
+ mLockMsgCondition.signal();
+ return Void();
+ default:
+ // do nothing
+ return Void();
+ }
+}
+
+Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type,
+ const FrontendScanMessage& message) {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mScanMsgProcessed) {
+ mMsgCondition.wait(mMsgLock);
+ }
+ ALOGD("[vts] frontend scan message. Type: %d", type);
+ mScanMessageReceived = true;
+ mScanMsgProcessed = false;
+ mScanMessageType = type;
+ mScanMessage = message;
+ mMsgCondition.signal();
+ return Void();
+}
+
+void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
+ Result result = frontend->tune(settings);
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mEventReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "Event not received within timeout";
+ mLockMsgReceived = false;
+ return;
+ }
+ }
+ mEventReceived = false;
+}
+
+void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
+ Result result = frontend->tune(settings);
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mLockMsgReceived) {
+ if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
+ mLockMsgReceived = false;
+ return;
+ }
+ }
+ mLockMsgReceived = false;
+}
+
+void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
+ FrontendScanType type) {
+ uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
+ if (type == FrontendScanType::SCAN_BLIND) {
+ // reset the frequency in the scan configuration to test blind scan. The settings param of
+ // passed in means the real input config on the transponder connected to the DUT.
+ // We want the blind the test to start from lower frequency than this to check the blind
+ // scan implementation.
+ resetBlindScanStartingFrequency(config, targetFrequency - 100);
+ }
+
+ Result result = frontend->scan(config.settings, type);
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ bool scanMsgLockedReceived = false;
+ bool targetFrequencyReceived = false;
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+wait:
+ while (!mScanMessageReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "Scan message not received within timeout";
+ mScanMessageReceived = false;
+ mScanMsgProcessed = true;
+ return;
+ }
+ }
+
+ if (mScanMessageType != FrontendScanMessageType::END) {
+ if (mScanMessageType == FrontendScanMessageType::LOCKED) {
+ scanMsgLockedReceived = true;
+ Result result = frontend->scan(config.settings, type);
+ EXPECT_TRUE(result == Result::SUCCESS);
+ }
+
+ if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
+ targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
+ mScanMessage.frequencies()[0] == targetFrequency;
+ }
+
+ if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
+ ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
+ }
+
+ mScanMessageReceived = false;
+ mScanMsgProcessed = true;
+ mMsgCondition.signal();
+ goto wait;
+ }
+
+ EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
+ EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
+ mScanMessageReceived = false;
+ mScanMsgProcessed = true;
+}
+
+uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
+ switch (type) {
+ case FrontendType::ANALOG:
+ return settings.analog().frequency;
+ case FrontendType::ATSC:
+ return settings.atsc().frequency;
+ case FrontendType::ATSC3:
+ return settings.atsc3().frequency;
+ case FrontendType::DVBC:
+ return settings.dvbc().frequency;
+ case FrontendType::DVBS:
+ return settings.dvbs().frequency;
+ case FrontendType::DVBT:
+ return settings.dvbt().frequency;
+ case FrontendType::ISDBS:
+ return settings.isdbs().frequency;
+ case FrontendType::ISDBS3:
+ return settings.isdbs3().frequency;
+ case FrontendType::ISDBT:
+ return settings.isdbt().frequency;
+ default:
+ return 0;
+ }
+}
+
+void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
+ uint32_t resetingFreq) {
+ switch (config.type) {
+ case FrontendType::ANALOG:
+ config.settings.analog().frequency = resetingFreq;
+ break;
+ case FrontendType::ATSC:
+ config.settings.atsc().frequency = resetingFreq;
+ break;
+ case FrontendType::ATSC3:
+ config.settings.atsc3().frequency = resetingFreq;
+ break;
+ case FrontendType::DVBC:
+ config.settings.dvbc().frequency = resetingFreq;
+ break;
+ case FrontendType::DVBS:
+ config.settings.dvbs().frequency = resetingFreq;
+ break;
+ case FrontendType::DVBT:
+ config.settings.dvbt().frequency = resetingFreq;
+ break;
+ case FrontendType::ISDBS:
+ config.settings.isdbs().frequency = resetingFreq;
+ break;
+ case FrontendType::ISDBS3:
+ config.settings.isdbs3().frequency = resetingFreq;
+ break;
+ case FrontendType::ISDBT:
+ config.settings.isdbt().frequency = resetingFreq;
+ break;
+ default:
+ // do nothing
+ return;
+ }
+}
+
+AssertionResult FrontendTests::getFrontendIds() {
+ Result status;
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ mFeIds = frontendIds;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) {
+ Result status;
+ mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
+ mFrontendInfo = frontendInfo;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) {
+ Result status;
+ mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
+ mFrontend = frontend;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::setFrontendCallback() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ mFrontendCallback = new FrontendCallback();
+ auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
+ return AssertionResult(callbackStatus.isOk());
+}
+
+AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
+ EXPECT_TRUE(mFrontendCallback)
+ << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
+
+ EXPECT_TRUE(mFrontendInfo.type == config.type)
+ << "FrontendConfig does not match the frontend info of the given id.";
+
+ mFrontendCallback->scanTest(mFrontend, config, type);
+ return AssertionResult(true);
+}
+
+AssertionResult FrontendTests::stopScanFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ Result status;
+ status = mFrontend->stopScan();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::tuneFrontend(FrontendConfig config) {
+ EXPECT_TRUE(mFrontendCallback)
+ << "test with openFrontendById/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 FrontendTests::stopTuneFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ Result status;
+ status = mFrontend->stopTune();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::closeFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ Result status;
+ status = mFrontend->close();
+ mFrontend = nullptr;
+ mFrontendCallback = nullptr;
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
+ 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 != feType) {
+ continue;
+ }
+ feId = mFeIds[i];
+ return;
+ }
+ feId = INVALID_ID;
+}
+
+void FrontendTests::tuneTest(FrontendConfig frontendConf) {
+ uint32_t feId;
+ getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(openFrontendById(feId));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(tuneFrontend(frontendConf));
+ ASSERT_TRUE(stopTuneFrontend());
+ ASSERT_TRUE(closeFrontend());
+}
+
+void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
+ uint32_t feId;
+ getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(openFrontendById(feId));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(scanFrontend(frontendConf, scanType));
+ ASSERT_TRUE(stopScanFrontend());
+ ASSERT_TRUE(closeFrontend());
+}
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
new file mode 100644
index 0000000..1a9bec9
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -0,0 +1,124 @@
+/*
+ * 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/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 <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>
+#include <utils/Mutex.h>
+#include <map>
+
+#include "VtsHalTvTunerV1_0TestConfigurations.h"
+
+#define WAIT_TIMEOUT 3000000000
+#define INVALID_ID -1
+
+using android::Condition;
+using android::IMemory;
+using android::IMemoryHeap;
+using android::MemoryDealer;
+using android::Mutex;
+using android::sp;
+using android::hardware::fromHeap;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
+using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
+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::IFrontend;
+using android::hardware::tv::tuner::V1_0::IFrontendCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+#define INVALID_ID -1
+#define WAIT_TIMEOUT 3000000000
+
+class FrontendCallback : public IFrontendCallback {
+ public:
+ virtual Return<void> onEvent(FrontendEventType frontendEventType) override;
+ virtual Return<void> onScanMessage(FrontendScanMessageType type,
+ const FrontendScanMessage& message) override;
+
+ void tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings);
+ void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
+ void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
+
+ // Helper methods
+ uint32_t getTargetFrequency(FrontendSettings settings, FrontendType type);
+ void resetBlindScanStartingFrequency(FrontendConfig& config, uint32_t resetingFreq);
+
+ private:
+ bool mEventReceived = false;
+ bool mScanMessageReceived = false;
+ bool mLockMsgReceived = false;
+ bool mScanMsgProcessed = true;
+ FrontendScanMessageType mScanMessageType;
+ FrontendScanMessage mScanMessage;
+ hidl_vec<uint8_t> mEventMessage;
+ android::Mutex mMsgLock;
+ android::Condition mMsgCondition;
+ android::Condition mLockMsgCondition;
+};
+
+class FrontendTests {
+ public:
+ sp<ITuner> mService;
+
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+
+ AssertionResult getFrontendIds();
+ AssertionResult getFrontendInfo(uint32_t frontendId);
+ AssertionResult openFrontendById(uint32_t frontendId);
+ AssertionResult setFrontendCallback();
+ AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
+ AssertionResult stopScanFrontend();
+ AssertionResult tuneFrontend(FrontendConfig config);
+ AssertionResult stopTuneFrontend();
+ AssertionResult closeFrontend();
+
+ void getFrontendIdByType(FrontendType feType, uint32_t& feId);
+ void tuneTest(FrontendConfig frontendConf);
+ void scanTest(FrontendConfig frontend, FrontendScanType type);
+
+ protected:
+ sp<IFrontend> mFrontend;
+ FrontendInfo mFrontendInfo;
+ sp<FrontendCallback> mFrontendCallback;
+ hidl_vec<FrontendId> mFeIds;
+};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 8b0413c..c44f77d 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -14,1095 +14,12 @@
* limitations under the License.
*/
-#define LOG_TAG "Tuner_hidl_hal_test"
-
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-#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 <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>
-#include <utils/Mutex.h>
-#include <fstream>
-#include <iostream>
-#include <map>
-
-#include "VtsHalTvTunerV1_0TestConfigurations.h"
-
-#define WAIT_TIMEOUT 3000000000
-
-using android::Condition;
-using android::IMemory;
-using android::IMemoryHeap;
-using android::MemoryDealer;
-using android::Mutex;
-using android::sp;
-using android::hardware::EventFlag;
-using android::hardware::fromHeap;
-using android::hardware::hidl_handle;
-using android::hardware::hidl_string;
-using android::hardware::hidl_vec;
-using android::hardware::HidlMemory;
-using android::hardware::kSynchronizedReadWrite;
-using android::hardware::MessageQueue;
-using android::hardware::MQDescriptorSync;
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::tv::tuner::V1_0::DataFormat;
-using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
-using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
-using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
-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::DemuxTsFilterSettings;
-using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
-using android::hardware::tv::tuner::V1_0::DvrSettings;
-using android::hardware::tv::tuner::V1_0::DvrType;
-using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
-using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
-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;
-using android::hardware::tv::tuner::V1_0::IDvr;
-using android::hardware::tv::tuner::V1_0::IDvrCallback;
-using android::hardware::tv::tuner::V1_0::IFilter;
-using android::hardware::tv::tuner::V1_0::IFilterCallback;
-using android::hardware::tv::tuner::V1_0::IFrontend;
-using android::hardware::tv::tuner::V1_0::IFrontendCallback;
-using android::hardware::tv::tuner::V1_0::ITuner;
-using android::hardware::tv::tuner::V1_0::PlaybackSettings;
-using android::hardware::tv::tuner::V1_0::PlaybackStatus;
-using android::hardware::tv::tuner::V1_0::RecordSettings;
-using android::hardware::tv::tuner::V1_0::RecordStatus;
-using android::hardware::tv::tuner::V1_0::Result;
-
-using ::testing::AssertionResult;
+#include "VtsHalTvTunerV1_0TargetTest.h"
namespace {
-using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-using MQDesc = MQDescriptorSync<uint8_t>;
-
-const std::vector<uint8_t> goldenDataOutputBuffer{
- 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
- 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
- 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
- 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
- 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
- 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
- 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
- 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
- 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
- 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
- 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
- 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
- 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
- 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
- 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
- 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
- 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
- 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
- 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
- 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
- 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
- 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
- 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
- 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
- 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
- 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
- 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
- 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
- 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
- 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
- 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
- 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
- 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
- 0x73, 0x63, 0x65, 0x6e, 0x65,
-};
-
-// const uint16_t FMQ_SIZE_4K = 0x1000;
-const uint32_t FMQ_SIZE_1M = 0x100000;
-const uint32_t FMQ_SIZE_16M = 0x1000000;
-
-enum FilterEventType : uint8_t {
- UNDEFINED,
- SECTION,
- MEDIA,
- PES,
- RECORD,
- MMTPRECORD,
- DOWNLOAD,
- TEMI,
-};
-
-struct PlaybackConf {
- string inputDataFile;
- PlaybackSettings setting;
-};
-
-/******************************** Start FrontendCallback **********************************/
-class FrontendCallback : public IFrontendCallback {
- public:
- virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
- android::Mutex::Autolock autoLock(mMsgLock);
- ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
- mEventReceived = true;
- mMsgCondition.signal();
- switch (frontendEventType) {
- case FrontendEventType::LOCKED:
- mLockMsgReceived = true;
- mLockMsgCondition.signal();
- return Void();
- default:
- // do nothing
- return Void();
- }
- }
-
- virtual Return<void> onScanMessage(FrontendScanMessageType type,
- const FrontendScanMessage& message) override {
- android::Mutex::Autolock autoLock(mMsgLock);
- while (!mScanMsgProcessed) {
- mMsgCondition.wait(mMsgLock);
- }
- ALOGD("[vts] frontend scan message. Type: %d", type);
- mScanMessageReceived = true;
- mScanMsgProcessed = false;
- mScanMessageType = type;
- mScanMessage = message;
- mMsgCondition.signal();
- return Void();
- }
-
- void tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings);
- void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
- void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
-
- // Helper methods
- uint32_t getTargetFrequency(FrontendSettings settings, FrontendType type);
- void resetBlindScanStartingFrequency(FrontendConfig config, uint32_t resetingFreq);
-
- private:
- bool mEventReceived = false;
- bool mScanMessageReceived = false;
- bool mLockMsgReceived = false;
- bool mScanMsgProcessed = true;
- FrontendScanMessageType mScanMessageType;
- FrontendScanMessage mScanMessage;
- hidl_vec<uint8_t> mEventMessage;
- android::Mutex mMsgLock;
- android::Condition mMsgCondition;
- android::Condition mLockMsgCondition;
-};
-
-void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
- Result result = frontend->tune(settings);
- EXPECT_TRUE(result == Result::SUCCESS);
-
- android::Mutex::Autolock autoLock(mMsgLock);
- while (!mEventReceived) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "Event not received within timeout";
- mLockMsgReceived = false;
- return;
- }
- }
- mEventReceived = false;
-}
-
-void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
- Result result = frontend->tune(settings);
- EXPECT_TRUE(result == Result::SUCCESS);
-
- android::Mutex::Autolock autoLock(mMsgLock);
- while (!mLockMsgReceived) {
- if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
- mLockMsgReceived = false;
- return;
- }
- }
- mLockMsgReceived = false;
-}
-
-void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
- FrontendScanType type) {
- uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
- if (type == FrontendScanType::SCAN_BLIND) {
- // reset the frequency in the scan configuration to test blind scan. The settings param of
- // passed in means the real input config on the transponder connected to the DUT.
- // We want the blind the test to start from lower frequency than this to check the blind
- // scan implementation.
- resetBlindScanStartingFrequency(config, targetFrequency - 100);
- }
-
- Result result = frontend->scan(config.settings, type);
- EXPECT_TRUE(result == Result::SUCCESS);
-
- bool scanMsgLockedReceived = false;
- bool targetFrequencyReceived = false;
-
- android::Mutex::Autolock autoLock(mMsgLock);
-wait:
- while (!mScanMessageReceived) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "Scan message not received within timeout";
- mScanMessageReceived = false;
- mScanMsgProcessed = true;
- return;
- }
- }
-
- if (mScanMessageType != FrontendScanMessageType::END) {
- if (mScanMessageType == FrontendScanMessageType::LOCKED) {
- scanMsgLockedReceived = true;
- Result result = frontend->scan(config.settings, type);
- EXPECT_TRUE(result == Result::SUCCESS);
- }
-
- if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
- targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
- mScanMessage.frequencies()[0] == targetFrequency;
- }
-
- if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
- ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
- }
-
- mScanMessageReceived = false;
- mScanMsgProcessed = true;
- mMsgCondition.signal();
- goto wait;
- }
-
- EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
- EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
- mScanMessageReceived = false;
- mScanMsgProcessed = true;
-}
-
-uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
- switch (type) {
- case FrontendType::ANALOG:
- return settings.analog().frequency;
- case FrontendType::ATSC:
- return settings.atsc().frequency;
- case FrontendType::ATSC3:
- return settings.atsc3().frequency;
- case FrontendType::DVBC:
- return settings.dvbc().frequency;
- case FrontendType::DVBS:
- return settings.dvbs().frequency;
- case FrontendType::DVBT:
- return settings.dvbt().frequency;
- case FrontendType::ISDBS:
- return settings.isdbs().frequency;
- case FrontendType::ISDBS3:
- return settings.isdbs3().frequency;
- case FrontendType::ISDBT:
- return settings.isdbt().frequency;
- default:
- return 0;
- }
-}
-
-void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig config,
- uint32_t resetingFreq) {
- switch (config.type) {
- case FrontendType::ANALOG:
- config.settings.analog().frequency = resetingFreq;
- break;
- case FrontendType::ATSC:
- config.settings.atsc().frequency = resetingFreq;
- break;
- case FrontendType::ATSC3:
- config.settings.atsc3().frequency = resetingFreq;
- break;
- case FrontendType::DVBC:
- config.settings.dvbc().frequency = resetingFreq;
- break;
- case FrontendType::DVBS:
- config.settings.dvbs().frequency = resetingFreq;
- break;
- case FrontendType::DVBT:
- config.settings.dvbt().frequency = resetingFreq;
- break;
- case FrontendType::ISDBS:
- config.settings.isdbs().frequency = resetingFreq;
- break;
- case FrontendType::ISDBS3:
- config.settings.isdbs3().frequency = resetingFreq;
- break;
- case FrontendType::ISDBT:
- config.settings.isdbt().frequency = resetingFreq;
- break;
- default:
- // do nothing
- return;
- }
-}
-/******************************** 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
- mFilterEvent = filterEvent;
- readFilterEventData();
- mPidFilterOutputCount++;
- // mFilterIdToMQ.erase(filterEvent.filterId);
-
- // startFilterEventThread(filterEvent);
- mMsgCondition.signal();
- return Void();
- }
-
- virtual Return<void> onFilterStatus(const DemuxFilterStatus /*status*/) override {
- return Void();
- }
-
- void setFilterId(uint32_t filterId) { mFilterId = filterId; }
- void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
- void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
-
- void testFilterDataOutput();
-
- void startFilterEventThread(DemuxFilterEvent event);
- static void* __threadLoopFilter(void* threadArgs);
- void filterThreadLoop(DemuxFilterEvent& event);
-
- void updateFilterMQ(MQDesc& filterMQDescriptor);
- void updateGoldenOutputMap(string goldenOutputFile);
- bool readFilterEventData();
- bool dumpAvData(DemuxFilterMediaEvent event);
-
- private:
- struct FilterThreadArgs {
- FilterCallback* user;
- DemuxFilterEvent event;
- };
- uint16_t mDataLength = 0;
- std::vector<uint8_t> mDataOutputBuffer;
-
- string mFilterIdToGoldenOutput;
-
- uint32_t mFilterId;
- sp<IFilter> mFilter;
- FilterEventType mFilterEventType;
- std::unique_ptr<FilterMQ> mFilterMQ;
- EventFlag* mFilterMQEventFlag;
- DemuxFilterEvent mFilterEvent;
-
- android::Mutex mMsgLock;
- android::Mutex mFilterOutputLock;
- android::Condition mMsgCondition;
- android::Condition mFilterOutputCondition;
-
- pthread_t mFilterThread;
-
- int mPidFilterOutputCount = 0;
-};
-
-void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
- struct FilterThreadArgs* threadArgs =
- (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
- threadArgs->user = this;
- threadArgs->event = event;
-
- pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
- pthread_setname_np(mFilterThread, "test_playback_input_loop");
-}
-
-void FilterCallback::testFilterDataOutput() {
- android::Mutex::Autolock autoLock(mMsgLock);
- while (mPidFilterOutputCount < 1) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
- return;
- }
- }
- mPidFilterOutputCount = 0;
- ALOGW("[vts] pass and stop");
-}
-
-void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
- 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) {
- mFilterIdToGoldenOutput = goldenOutputFile;
-}
-
-void* FilterCallback::__threadLoopFilter(void* threadArgs) {
- FilterCallback* const self =
- static_cast<FilterCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
- self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
- return 0;
-}
-
-void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
- android::Mutex::Autolock autoLock(mFilterOutputLock);
- // Read from mFilterMQ[event.filterId] per event and filter type
-
- // Assemble to filterOutput[filterId]
-
- // check if filterOutput[filterId] matches goldenOutput[filterId]
-
- // If match, remove filterId entry from MQ map
-
- // end thread
-}
-
-bool FilterCallback::readFilterEventData() {
- bool result = false;
- DemuxFilterEvent filterEvent = mFilterEvent;
- ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
- // todo separate filter handlers
- for (int i = 0; i < filterEvent.events.size(); i++) {
- switch (mFilterEventType) {
- case FilterEventType::SECTION:
- mDataLength = filterEvent.events[i].section().dataLength;
- break;
- case FilterEventType::PES:
- mDataLength = filterEvent.events[i].pes().dataLength;
- break;
- case FilterEventType::MEDIA:
- return dumpAvData(filterEvent.events[i].media());
- case FilterEventType::RECORD:
- break;
- case FilterEventType::MMTPRECORD:
- break;
- case FilterEventType::DOWNLOAD:
- break;
- default:
- break;
- }
- // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
- // match";
-
- mDataOutputBuffer.resize(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";
- }*/
- }
- mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
- return result;
-}
-
-bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
- uint32_t length = event.dataLength;
- uint64_t dataId = event.avDataId;
- // read data from buffer pointed by a handle
- hidl_handle handle = event.avMemory;
-
- int av_fd = handle.getNativeHandle()->data[0];
- uint8_t* buffer = static_cast<uint8_t*>(
- mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0 /*offset*/));
- if (buffer == MAP_FAILED) {
- ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
- return false;
- }
- uint8_t output[length + 1];
- memcpy(output, buffer, length);
- // print buffer and check with golden output.
- EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
- return true;
-}
-/******************************** End FilterCallback **********************************/
-
-/******************************** Start DvrCallback **********************************/
-class DvrCallback : public IDvrCallback {
- public:
- virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
- ALOGW("[vts] record status %hhu", status);
- switch (status) {
- case DemuxFilterStatus::DATA_READY:
- break;
- case DemuxFilterStatus::LOW_WATER:
- break;
- case DemuxFilterStatus::HIGH_WATER:
- case DemuxFilterStatus::OVERFLOW:
- ALOGW("[vts] record overflow. Flushing");
- break;
- }
- return Void();
- }
-
- virtual Return<void> onPlaybackStatus(PlaybackStatus status) override {
- // android::Mutex::Autolock autoLock(mMsgLock);
- ALOGW("[vts] playback status %d", status);
- switch (status) {
- case PlaybackStatus::SPACE_EMPTY:
- case PlaybackStatus::SPACE_ALMOST_EMPTY:
- ALOGW("[vts] keep playback inputing %d", status);
- mKeepWritingPlaybackFMQ = true;
- break;
- case PlaybackStatus::SPACE_ALMOST_FULL:
- case PlaybackStatus::SPACE_FULL:
- ALOGW("[vts] stop playback inputing %d", status);
- mKeepWritingPlaybackFMQ = false;
- break;
- }
- return Void();
- }
-
- void testFilterDataOutput();
- void stopPlaybackThread();
- void testRecordOutput();
- void stopRecordThread();
-
- void startPlaybackInputThread(PlaybackConf playbackConf, MQDesc& playbackMQDescriptor);
- void startRecordOutputThread(RecordSettings recordSetting, MQDesc& recordMQDescriptor);
- static void* __threadLoopPlayback(void* threadArgs);
- static void* __threadLoopRecord(void* threadArgs);
- void playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ);
- void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
-
- bool readRecordFMQ();
-
- private:
- struct PlaybackThreadArgs {
- DvrCallback* user;
- PlaybackConf* playbackConf;
- bool* keepWritingPlaybackFMQ;
- };
- struct RecordThreadArgs {
- DvrCallback* user;
- RecordSettings* recordSetting;
- bool* keepReadingRecordFMQ;
- };
- uint16_t mDataLength = 0;
- std::vector<uint8_t> mDataOutputBuffer;
-
- std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
- std::unique_ptr<FilterMQ> mPlaybackMQ;
- std::unique_ptr<FilterMQ> mRecordMQ;
- std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
-
- android::Mutex mMsgLock;
- android::Mutex mPlaybackThreadLock;
- android::Mutex mRecordThreadLock;
- android::Condition mMsgCondition;
-
- bool mKeepWritingPlaybackFMQ = true;
- bool mKeepReadingRecordFMQ = true;
- bool mPlaybackThreadRunning;
- bool mRecordThreadRunning;
- pthread_t mPlaybackThread;
- pthread_t mRecordThread;
-
- int mPidFilterOutputCount = 0;
-};
-
-void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf,
- MQDesc& playbackMQDescriptor) {
- mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(mPlaybackMQ);
- struct PlaybackThreadArgs* threadArgs =
- (struct PlaybackThreadArgs*)malloc(sizeof(struct PlaybackThreadArgs));
- threadArgs->user = this;
- threadArgs->playbackConf = &playbackConf;
- threadArgs->keepWritingPlaybackFMQ = &mKeepWritingPlaybackFMQ;
-
- pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, (void*)threadArgs);
- pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
-}
-
-void DvrCallback::stopPlaybackThread() {
- mPlaybackThreadRunning = false;
- mKeepWritingPlaybackFMQ = false;
-
- android::Mutex::Autolock autoLock(mPlaybackThreadLock);
-}
-
-void* DvrCallback::__threadLoopPlayback(void* threadArgs) {
- DvrCallback* const self =
- static_cast<DvrCallback*>(((struct PlaybackThreadArgs*)threadArgs)->user);
- self->playbackThreadLoop(((struct PlaybackThreadArgs*)threadArgs)->playbackConf,
- ((struct PlaybackThreadArgs*)threadArgs)->keepWritingPlaybackFMQ);
- return 0;
-}
-
-void DvrCallback::playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ) {
- android::Mutex::Autolock autoLock(mPlaybackThreadLock);
- mPlaybackThreadRunning = true;
-
- // Create the EventFlag that is used to signal the HAL impl that data have been
- // written into the Playback FMQ
- EventFlag* playbackMQEventFlag;
- EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
- android::OK);
-
- // open the stream and get its length
- std::ifstream inputData(playbackConf->inputDataFile, std::ifstream::binary);
- int writeSize = playbackConf->setting.packetSize * 6;
- char* buffer = new char[writeSize];
- ALOGW("[vts] playback thread loop start %s", playbackConf->inputDataFile.c_str());
- if (!inputData.is_open()) {
- mPlaybackThreadRunning = false;
- ALOGW("[vts] Error %s", strerror(errno));
- }
-
- while (mPlaybackThreadRunning) {
- // move the stream pointer for packet size * 6 every read until the end
- while (*keepWritingPlaybackFMQ) {
- inputData.read(buffer, writeSize);
- if (!inputData) {
- int leftSize = inputData.gcount();
- if (leftSize == 0) {
- mPlaybackThreadRunning = false;
- break;
- }
- inputData.clear();
- inputData.read(buffer, leftSize);
- // Write the left over of the input data and quit the thread
- if (leftSize > 0) {
- EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
- playbackMQEventFlag->wake(
- static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
- }
- mPlaybackThreadRunning = false;
- break;
- }
- // Write input FMQ and notify the Tuner Implementation
- EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
- playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
- inputData.seekg(writeSize, inputData.cur);
- sleep(1);
- }
- }
-
- ALOGW("[vts] Playback thread end.");
-
- delete[] buffer;
- inputData.close();
-}
-
-void DvrCallback::testRecordOutput() {
- android::Mutex::Autolock autoLock(mMsgLock);
- while (mDataOutputBuffer.empty()) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
- return;
- }
- }
- stopRecordThread();
- ALOGW("[vts] record pass and stop");
-}
-
-void DvrCallback::startRecordOutputThread(RecordSettings recordSetting,
- MQDesc& recordMQDescriptor) {
- mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(mRecordMQ);
- struct RecordThreadArgs* threadArgs =
- (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
- threadArgs->user = this;
- threadArgs->recordSetting = &recordSetting;
- threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
-
- pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
- pthread_setname_np(mRecordThread, "test_record_input_loop");
-}
-
-void* DvrCallback::__threadLoopRecord(void* threadArgs) {
- DvrCallback* const self =
- static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
- self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSetting,
- ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
- return 0;
-}
-
-void DvrCallback::recordThreadLoop(RecordSettings* /*recordSetting*/, bool* keepReadingRecordFMQ) {
- ALOGD("[vts] DvrCallback record threadLoop start.");
- android::Mutex::Autolock autoLock(mRecordThreadLock);
- mRecordThreadRunning = true;
-
- // Create the EventFlag that is used to signal the HAL impl that data have been
- // read from the Record FMQ
- EventFlag* recordMQEventFlag;
- EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
- android::OK);
-
- while (mRecordThreadRunning) {
- while (*keepReadingRecordFMQ) {
- uint32_t efState = 0;
- android::status_t status = recordMQEventFlag->wait(
- static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
- true /* retry on spurious wake */);
- if (status != android::OK) {
- ALOGD("[vts] wait for data ready on the record FMQ");
- continue;
- }
- // Our current implementation filter the data and write it into the filter FMQ
- // immediately after the DATA_READY from the VTS/framework
- if (!readRecordFMQ()) {
- ALOGD("[vts] record data failed to be filtered. Ending thread");
- mRecordThreadRunning = false;
- break;
- }
- }
- }
-
- mRecordThreadRunning = false;
- ALOGD("[vts] record thread ended.");
-}
-
-bool DvrCallback::readRecordFMQ() {
- android::Mutex::Autolock autoLock(mMsgLock);
- bool result = false;
- mDataOutputBuffer.clear();
- mDataOutputBuffer.resize(mRecordMQ->availableToRead());
- result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
- EXPECT_TRUE(result) << "can't read from Record MQ";
- mMsgCondition.signal();
- return result;
-}
-
-void DvrCallback::stopRecordThread() {
- mKeepReadingRecordFMQ = false;
- 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;
- sp<IDvr> mDvr;
- sp<IFilter> mFilter;
- std::map<uint32_t, sp<IFilter>> mFilters;
- std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
-
- sp<FilterCallback> mFilterCallback;
- sp<DvrCallback> mDvrCallback;
- MQDesc mFilterMQDescriptor;
- MQDesc mDvrMQDescriptor;
- MQDesc mRecordMQDescriptor;
- vector<uint32_t> mUsedFilterIds;
- hidl_vec<FrontendId> mFeIds;
-
- uint32_t mDemuxId;
- uint32_t mFilterId = -1;
-
- pthread_t mPlaybackshread;
- bool mPlaybackThreadRunning;
-
- 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();
-
- 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);
-};
-
-/*========================== Start Frontend APIs Tests Implementation ==========================*/
-AssertionResult TunerHidlTest::getFrontendIds() {
+AssertionResult TunerHidlTest::createDescrambler(uint32_t demuxId) {
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;
- });
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::setFrontendCallback() {
- EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
- mFrontendCallback = new FrontendCallback();
- auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
- return AssertionResult(callbackStatus.isOk());
-}
-
-AssertionResult TunerHidlTest::scanFrontend(FrontendConfig config, FrontendScanType type) {
- 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->scanTest(mFrontend, config, type);
- return AssertionResult(true);
-}
-
-AssertionResult TunerHidlTest::stopScanFrontend() {
- EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
- Result status;
- 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 AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::closeFrontend() {
- EXPECT_TRUE(mFrontend) << "Test with openFrontend first.";
- Result status;
- status = mFrontend->close();
- mFrontend = nullptr;
- mFrontendCallback = nullptr;
- return AssertionResult(status == Result::SUCCESS);
-}
-/*=========================== End Frontend APIs Tests Implementation ===========================*/
-
-/*============================ 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 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());
-}
-
-AssertionResult TunerHidlTest::closeDemux() {
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- auto status = mDemux->close();
- mDemux = nullptr;
- return AssertionResult(status.isOk());
-}
-
-AssertionResult TunerHidlTest::openFilterInDemux(DemuxFilterType type) {
- Result status;
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
-
- // Create demux callback
- mFilterCallback = new FilterCallback();
-
- // Add filter to the local demux
- mDemux->openFilter(type, FMQ_SIZE_16M, mFilterCallback,
- [&](Result result, const sp<IFilter>& filter) {
- mFilter = filter;
- status = result;
- });
-
- 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) {
- mFilterCallback->setFilterId(mFilterId);
- mFilterCallback->setFilterInterface(mFilter);
- mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
- mFilters[mFilterId] = mFilter;
- mFilterCallbacks[mFilterId] = mFilterCallback;
- filterId = mFilterId;
- }
-
- return AssertionResult(status == Result::SUCCESS);
-}
-
-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;
@@ -1111,595 +28,333 @@
return failure();
}
- status = mDescrambler->setDemuxSource(mDemuxId);
+ status = mDescrambler->setDemuxSource(demuxId);
if (status != Result::SUCCESS) {
return failure();
}
// Test if demux source can be set more than once.
- status = mDescrambler->setDemuxSource(mDemuxId);
+ status = mDescrambler->setDemuxSource(demuxId);
return AssertionResult(status == Result::INVALID_STATE);
}
AssertionResult TunerHidlTest::closeDescrambler() {
Result status;
- if (!mDescrambler && createDescrambler() == failure()) {
- return failure();
- }
+ EXPECT_TRUE(mDescrambler);
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.";
-
+AssertionResult TunerBroadcastHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
// Data Verify Module
std::map<uint32_t, sp<FilterCallback>>::iterator it;
- for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
+ std::map<uint32_t, sp<FilterCallback>> filterCallbacks = mFilterTests.getFilterCallbacks();
+ for (it = filterCallbacks.begin(); it != filterCallbacks.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();
- }
-
+AssertionResult TunerPlaybackHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
// Data Verify Module
std::map<uint32_t, sp<FilterCallback>>::iterator it;
- for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
+ std::map<uint32_t, sp<FilterCallback>> filterCallbacks = mFilterTests.getFilterCallbacks();
+ for (it = filterCallbacks.begin(); it != filterCallbacks.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();
+ return success();
}
-AssertionResult TunerHidlTest::recordDataFlowTest(vector<FilterConf> filterConf,
- RecordSettings recordSetting,
- vector<string> goldenOutputFiles) {
- Result status;
- hidl_vec<FrontendId> feIds;
+void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
+ FrontendConfig frontendConf) {
+ uint32_t feId;
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ uint32_t filterId;
- 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:
- switch (type.subType.tsFilterType()) {
- case DemuxTsFilterType::UNDEFINED:
- break;
- case DemuxTsFilterType::SECTION:
- eventType = FilterEventType::SECTION;
- break;
- case DemuxTsFilterType::PES:
- eventType = FilterEventType::PES;
- break;
- case DemuxTsFilterType::TS:
- break;
- case DemuxTsFilterType::AUDIO:
- case DemuxTsFilterType::VIDEO:
- eventType = FilterEventType::MEDIA;
- break;
- case DemuxTsFilterType::PCR:
- break;
- case DemuxTsFilterType::RECORD:
- eventType = FilterEventType::RECORD;
- break;
- case DemuxTsFilterType::TEMI:
- eventType = FilterEventType::TEMI;
- break;
- }
- break;
- case DemuxFilterMainType::MMTP:
- /*mmtpSettings*/
- break;
- case DemuxFilterMainType::IP:
- /*ipSettings*/
- break;
- case DemuxFilterMainType::TLV:
- /*tlvSettings*/
- break;
- case DemuxFilterMainType::ALP:
- /*alpSettings*/
- break;
- default:
- break;
- }
- return eventType;
-}
-/*============================== End Helper Functions ==============================*/
-/***************************** End Test Implementation *****************************/
-
-/******************************** 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);
+ mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFilterTests.setDemux(demux);
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+ ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
}
-TEST_P(TunerHidlTest, openFrontend) {
- description("Open all the existing Frontends and close them");
- ASSERT_TRUE(getFrontendIds());
- ASSERT_TRUE(mFeIds.size() > 0);
+void TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
+ FrontendConfig frontendConf) {
+ uint32_t feId;
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ uint32_t filterId;
- for (size_t i = 0; i < mFeIds.size(); i++) {
- ASSERT_TRUE(openFrontend(mFeIds[i]));
- ASSERT_TRUE(closeFrontend());
+ mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+ if (feId == INVALID_ID) {
+ // TODO broadcast test on Cuttlefish needs licensed ts input,
+ // these tests are runnable on vendor device with real frontend module
+ // or with manual ts installing and use DVBT frontend.
+ return;
}
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFilterTests.setDemux(demux);
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+ ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
+ // tune test
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
}
-TEST_P(TunerHidlTest, TuneFrontend) {
+void TunerPlaybackHidlTest::playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf) {
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ uint32_t filterId;
+
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ mFilterTests.setDemux(demux);
+ mDvrTests.setDemux(demux);
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+ ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+ mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile, dvrConf.settings.playback());
+ ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
+ ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+ mDvrTests.stopPlaybackThread();
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+ mDvrTests.closeDvr();
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
+ FrontendConfig frontendConf, DvrConfig dvrConf) {
+ uint32_t feId;
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ uint32_t filterId;
+ sp<IFilter> filter;
+
+ mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFilterTests.setDemux(demux);
+ mDvrTests.setDemux(demux);
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+ ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+ filter = mFilterTests.getFilterById(filterId);
+ ASSERT_TRUE(filter != nullptr);
+ mDvrTests.startRecordOutputThread(dvrConf.settings.record());
+ ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
+ ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ mDvrTests.testRecordOutput();
+ mDvrTests.stopRecordThread();
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
+ ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+ mDvrTests.closeDvr();
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+void TunerRecordHidlTest::attachSingleFilterToRecordDvrTest(FilterConfig filterConf,
+ FrontendConfig frontendConf,
+ DvrConfig dvrConf) {
+ uint32_t feId;
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ uint32_t filterId;
+ sp<IFilter> filter;
+
+ mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFilterTests.setDemux(demux);
+ mDvrTests.setDemux(demux);
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+ ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+ filter = mFilterTests.getFilterById(filterId);
+ ASSERT_TRUE(filter != nullptr);
+ ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
+ ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
+ ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+ mDvrTests.closeDvr();
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+TEST_P(TunerFrontendHidlTest, TuneFrontend) {
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(tuneFrontend(frontendArray[0]));
- ASSERT_TRUE(stopTuneFrontend());
- ASSERT_TRUE(closeFrontend());
- break;
- }
+ mFrontendTests.tuneTest(frontendArray[DVBT]);
}
-TEST_P(TunerHidlTest, AutoScanFrontend) {
+TEST_P(TunerFrontendHidlTest, AutoScanFrontend) {
description("Run an auto frontend scan with specific setting and check lock scanMessage");
- 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(scanFrontend(frontendScanArray[0], FrontendScanType::SCAN_AUTO));
- ASSERT_TRUE(stopScanFrontend());
- ASSERT_TRUE(closeFrontend());
- break;
- }
+ mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_AUTO);
}
-TEST_P(TunerHidlTest, BlindScanFrontend) {
+TEST_P(TunerFrontendHidlTest, BlindScanFrontend) {
description("Run an blind frontend scan with specific setting and check lock scanMessage");
- 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(scanFrontend(frontendScanArray[0], FrontendScanType::SCAN_BLIND));
- ASSERT_TRUE(stopScanFrontend());
- ASSERT_TRUE(closeFrontend());
- break;
- }
-}
-/*=============================== End Frontend Tests ===============================*/
-
-/*============================ 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;
- }
+ mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
}
-TEST_P(TunerHidlTest, OpenFilterInDemux) {
- description("Open a filter in Demux.");
- 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(closeFilter(filterId));
- ASSERT_TRUE(closeDemux());
- ASSERT_TRUE(closeFrontend());
- break;
- }
+TEST_P(TunerDemuxHidlTest, openDemux) {
+ description("Open and close a Demux.");
+ uint32_t feId;
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
}
-TEST_P(TunerHidlTest, StartFilterInDemux) {
+TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
description("Open and start a filter in Demux.");
- 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));
- ASSERT_TRUE(stopFilter(filterId));
- ASSERT_TRUE(closeFilter(filterId));
- ASSERT_TRUE(closeDemux());
- ASSERT_TRUE(closeFrontend());
- break;
- }
-}
-/*============================ End Demux/Filter Tests ============================*/
-
-/*============================ Start Descrambler Tests ============================*/
-/*
- * TODO: re-enable the tests after finalizing the test refactoring.
- */
-/*TEST_P(TunerHidlTest, CreateDescrambler) {
- description("Create Descrambler");
- ASSERT_TRUE(createDescrambler());
+ // TODO use paramterized tests
+ configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
}
-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;
- }
+TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowVideoFilterTest) {
+ description("Test Video Filter functionality in Broadcast use case.");
+ broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBS]);
}
-/*
- * TODO: re-enable the tests after finalizing the testing stream.
- */
-/*TEST_P(TunerHidlTest, PlaybackDataFlowWithSectionFilterTest) {
- description("Feed ts data from playback and configure pes filter to get output");
-
- // todo modulize the filter conf parser
- vector<FilterConf> filterConf;
- filterConf.resize(1);
-
- DemuxFilterSettings filterSetting;
- DemuxTsFilterSettings tsFilterSetting{
- .tpid = 18,
- };
- DemuxFilterSectionSettings sectionFilterSetting;
- tsFilterSetting.filterSettings.section(sectionFilterSetting);
- filterSetting.ts(tsFilterSetting);
-
- DemuxFilterType type{
- .mainType = DemuxFilterMainType::TS,
- };
- type.subType.tsFilterType(DemuxTsFilterType::SECTION);
- FilterConf sectionFilterConf{
- .type = type,
- .setting = filterSetting,
- };
- filterConf[0] = sectionFilterConf;
-
- PlaybackSettings playbackSetting{
- .statusMask = 0xf,
- .lowThreshold = 0x1000,
- .highThreshold = 0x07fff,
- .dataFormat = DataFormat::TS,
- .packetSize = 188,
- };
-
- PlaybackConf playbackConf{
- .inputDataFile = "/vendor/etc/test1.ts",
- .setting = playbackSetting,
- };
-
- vector<string> goldenOutputFiles;
-
- ASSERT_TRUE(playbackDataFlowTest(filterConf, playbackConf, goldenOutputFiles));
+TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowAudioFilterTest) {
+ description("Test Audio Filter functionality in Broadcast use case.");
+ broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[DVBS]);
}
-TEST_P(TunerHidlTest, RecordDataFlowWithTsRecordFilterTest) {
- description("Feed ts data from frontend to recording and test with ts record filter");
+TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowSectionFilterTest) {
+ description("Test Section Filter functionality in Broadcast use case.");
+ broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[DVBS]);
+}
- // todo modulize the filter conf parser
- vector<FilterConf> filterConf;
- filterConf.resize(1);
-
- DemuxFilterSettings filterSetting;
- DemuxTsFilterSettings tsFilterSetting{
- .tpid = 119,
- };
- DemuxFilterRecordSettings recordFilterSetting;
- tsFilterSetting.filterSettings.record(recordFilterSetting);
- filterSetting.ts(tsFilterSetting);
-
- DemuxFilterType type{
- .mainType = DemuxFilterMainType::TS,
- };
- type.subType.tsFilterType(DemuxTsFilterType::RECORD);
- FilterConf recordFilterConf{
- .type = type,
- .setting = filterSetting,
- };
- filterConf[0] = recordFilterConf;
-
- RecordSettings recordSetting{
- .statusMask = 0xf,
- .lowThreshold = 0x1000,
- .highThreshold = 0x07fff,
- .dataFormat = DataFormat::TS,
- .packetSize = 188,
- };
-
- vector<string> goldenOutputFiles;
-
- ASSERT_TRUE(recordDataFlowTest(filterConf, recordSetting, goldenOutputFiles));
-}*/
-
-TEST_P(TunerHidlTest, AvBufferTest) {
+TEST_P(TunerBroadcastHidlTest, IonBufferTest) {
description("Test the av filter data bufferring.");
-
- 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[1].type) {
- continue;
- }
- ASSERT_TRUE(openFrontend(mFeIds[i]));
- ASSERT_TRUE(setFrontendCallback());
- ASSERT_TRUE(openDemux());
- ASSERT_TRUE(openFilterInDemux(filterArray[0].type));
- uint32_t filterId;
- ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
- ASSERT_TRUE(configFilter(filterArray[0].setting, filterId));
- ASSERT_TRUE(startFilter(filterId));
- ASSERT_TRUE(setDemuxFrontendDataSource(mFeIds[i]));
- // tune test
- ASSERT_TRUE(tuneFrontend(frontendArray[1]));
- // 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;
- }
+ broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBS]);
}
-/*============================== End Data Flow Tests ==============================*/
-/******************************** End Test Entry **********************************/
-} // namespace
+
+TEST_P(TunerPlaybackHidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
+ description("Feed ts data from playback and configure Ts section filter to get output");
+ playbackSingleFilterTest(filterArray[TS_SECTION0], dvrArray[DVR_PLAYBACK0]);
+}
+
+TEST_P(TunerRecordHidlTest, AttachFiltersToRecordTest) {
+ description("Attach a single filter to the record dvr test.");
+ // TODO use paramterized tests
+ attachSingleFilterToRecordDvrTest(filterArray[TS_RECORD0], frontendArray[DVBT],
+ dvrArray[DVR_RECORD0]);
+}
+
+TEST_P(TunerRecordHidlTest, RecordDataFlowWithTsRecordFilterTest) {
+ description("Feed ts data from frontend to recording and test with ts record filter");
+ recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
+}
+
+TEST_P(TunerHidlTest, CreateDescrambler) {
+ description("Create Descrambler");
+ uint32_t feId;
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ ASSERT_TRUE(createDescrambler(demuxId));
+ ASSERT_TRUE(closeDescrambler());
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerFrontendHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerDemuxHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerFilterHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerBroadcastHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerPlaybackHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerRecordHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
android::hardware::PrintInstanceNameToString);
+} // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
new file mode 100644
index 0000000..21a9855
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -0,0 +1,219 @@
+/*
+ * 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/hardware/tv/tuner/1.0/IDescrambler.h>
+
+#include "DemuxTests.h"
+#include "DvrTests.h"
+#include "FrontendTests.h"
+
+using android::hardware::tv::tuner::V1_0::DataFormat;
+using android::hardware::tv::tuner::V1_0::IDescrambler;
+
+static AssertionResult failure() {
+ return ::testing::AssertionFailure();
+}
+
+static AssertionResult success() {
+ return ::testing::AssertionSuccess();
+}
+
+namespace {
+
+void initConfiguration() {
+ initFrontendConfig();
+ initFrontendScanConfig();
+ initFilterConfig();
+ initDvrConfig();
+}
+
+class TunerFrontendHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mFrontendTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+};
+
+class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+};
+
+class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ mFilterTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+ FilterTests mFilterTests;
+};
+
+class TunerBroadcastHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ mFilterTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+ FilterTests mFilterTests;
+
+ AssertionResult filterDataOutputTest(vector<string> goldenOutputFiles);
+
+ void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
+};
+
+class TunerPlaybackHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ mFilterTests.setService(mService);
+ mDvrTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+ FilterTests mFilterTests;
+ DvrTests mDvrTests;
+
+ AssertionResult filterDataOutputTest(vector<string> goldenOutputFiles);
+
+ void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf);
+};
+
+class TunerRecordHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ mFilterTests.setService(mService);
+ mDvrTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ void attachSingleFilterToRecordDvrTest(FilterConfig filterConf, FrontendConfig frontendConf,
+ DvrConfig dvrConf);
+ void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
+ DvrConfig dvrConf);
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+ FilterTests mFilterTests;
+ DvrTests mDvrTests;
+};
+
+class TunerHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+
+ sp<IDescrambler> mDescrambler;
+
+ AssertionResult createDescrambler(uint32_t demuxId);
+ AssertionResult closeDescrambler();
+};
+} // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 31e3b51..b84013b 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -14,43 +14,23 @@
* 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::DataFormat;
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::DemuxRecordScIndexType;
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::DvrSettings;
+using android::hardware::tv::tuner::V1_0::DvrType;
using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
@@ -61,17 +41,48 @@
using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
using android::hardware::tv::tuner::V1_0::FrontendSettings;
using android::hardware::tv::tuner::V1_0::FrontendType;
+using android::hardware::tv::tuner::V1_0::PlaybackSettings;
+using android::hardware::tv::tuner::V1_0::RecordSettings;
-namespace {
+using namespace std;
-#define frontend_transponders_count 2
-#define channels_count 1
-#define frontend_scan_count 1
-#define filter_count 2
+const uint32_t FMQ_SIZE_1M = 0x100000;
+const uint32_t FMQ_SIZE_4M = 0x400000;
+const uint32_t FMQ_SIZE_16M = 0x1000000;
+
+typedef enum {
+ TS_VIDEO0,
+ TS_VIDEO1,
+ TS_AUDIO0,
+ TS_PES0,
+ TS_PCR0,
+ TS_SECTION0,
+ TS_TS0,
+ TS_RECORD0,
+ FILTER_MAX,
+} Filter;
+
+typedef enum {
+ DVBT,
+ DVBS,
+ FRONTEND_MAX,
+} Frontend;
+
+typedef enum {
+ SCAN_DVBT,
+ SCAN_MAX,
+} FrontendScan;
+
+typedef enum {
+ DVR_RECORD0,
+ DVR_PLAYBACK0,
+ DVR_MAX,
+} Dvr;
struct FilterConfig {
+ uint32_t bufferSize;
DemuxFilterType type;
- DemuxFilterSettings setting;
+ DemuxFilterSettings settings;
};
struct FrontendConfig {
@@ -87,10 +98,18 @@
DemuxTpid audioPid;
};
-static FrontendConfig frontendArray[frontend_transponders_count];
-static FrontendConfig frontendScanArray[channels_count];
-static ChannelConfig channelArray[frontend_scan_count];
-static FilterConfig filterArray[filter_count];
+struct DvrConfig {
+ DvrType type;
+ uint32_t bufferSize;
+ DvrSettings settings;
+ string playbackInputFile;
+};
+
+static FrontendConfig frontendArray[FILTER_MAX];
+static FrontendConfig frontendScanArray[SCAN_MAX];
+static ChannelConfig channelArray[FRONTEND_MAX];
+static FilterConfig filterArray[FILTER_MAX];
+static DvrConfig dvrArray[DVR_MAX];
static vector<string> goldenOutputFiles;
/** Configuration array for the frontend tune test */
@@ -107,14 +126,14 @@
.isHighPriority = true,
.standard = FrontendDvbtStandard::T,
};
- frontendArray[0].type = FrontendType::DVBT, frontendArray[0].settings.dvbt(dvbtSettings);
- frontendArray[1].type = FrontendType::DVBS;
+ frontendArray[DVBT].type = FrontendType::DVBT, frontendArray[DVBT].settings.dvbt(dvbtSettings);
+ frontendArray[DVBS].type = FrontendType::DVBS;
};
/** Configuration array for the frontend scan test */
inline void initFrontendScanConfig() {
- frontendScanArray[0].type = FrontendType::DVBT;
- frontendScanArray[0].settings.dvbt({
+ frontendScanArray[SCAN_DVBT].type = FrontendType::DVBT;
+ frontendScanArray[SCAN_DVBT].settings.dvbt({
.frequency = 578000,
.transmissionMode = FrontendDvbtTransmissionMode::MODE_8K,
.bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
@@ -130,19 +149,82 @@
/** 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 = 119;
- filterArray[0].setting.ts().filterSettings.av({.isPassthrough = false});
+ // TS VIDEO filter setting for default implementation testing
+ filterArray[TS_VIDEO0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_VIDEO0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+ filterArray[TS_VIDEO0].bufferSize = FMQ_SIZE_16M;
+ filterArray[TS_VIDEO0].settings.ts().tpid = 256;
+ filterArray[TS_VIDEO0].settings.ts().filterSettings.av({.isPassthrough = false});
+ filterArray[TS_VIDEO1].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_VIDEO1].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+ filterArray[TS_VIDEO1].bufferSize = FMQ_SIZE_16M;
+ filterArray[TS_VIDEO1].settings.ts().tpid = 256;
+ filterArray[TS_VIDEO1].settings.ts().filterSettings.av({.isPassthrough = false});
+ // TS AUDIO filter setting
+ filterArray[TS_AUDIO0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_AUDIO0].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
+ filterArray[TS_AUDIO0].bufferSize = FMQ_SIZE_16M;
+ filterArray[TS_AUDIO0].settings.ts().tpid = 256;
+ filterArray[TS_AUDIO0].settings.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,
+ filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES);
+ filterArray[TS_PES0].bufferSize = FMQ_SIZE_16M;
+ filterArray[TS_PES0].settings.ts().tpid = 256;
+ filterArray[TS_PES0].settings.ts().filterSettings.pesData({
+ .isRaw = false,
.streamId = 0xbd,
});
+ // TS PCR filter setting
+ filterArray[TS_PCR0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_PCR0].type.subType.tsFilterType(DemuxTsFilterType::PCR);
+ filterArray[TS_PCR0].bufferSize = FMQ_SIZE_16M;
+ filterArray[TS_PCR0].settings.ts().tpid = 256;
+ filterArray[TS_PCR0].settings.ts().filterSettings.noinit();
+ // TS filter setting
+ filterArray[TS_TS0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_TS0].type.subType.tsFilterType(DemuxTsFilterType::TS);
+ filterArray[TS_TS0].bufferSize = FMQ_SIZE_16M;
+ filterArray[TS_TS0].settings.ts().tpid = 256;
+ filterArray[TS_TS0].settings.ts().filterSettings.noinit();
+ // TS SECTION filter setting
+ filterArray[TS_SECTION0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_SECTION0].type.subType.tsFilterType(DemuxTsFilterType::SECTION);
+ filterArray[TS_SECTION0].bufferSize = FMQ_SIZE_16M;
+ filterArray[TS_SECTION0].settings.ts().tpid = 256;
+ filterArray[TS_SECTION0].settings.ts().filterSettings.section({
+ .isRaw = false,
+ });
+ // TS RECORD filter setting
+ filterArray[TS_RECORD0].type.mainType = DemuxFilterMainType::TS;
+ filterArray[TS_RECORD0].type.subType.tsFilterType(DemuxTsFilterType::RECORD);
+ filterArray[TS_RECORD0].settings.ts().tpid = 81;
+ filterArray[TS_RECORD0].settings.ts().filterSettings.record({
+ .scIndexType = DemuxRecordScIndexType::NONE,
+ });
};
-} // namespace
+/** Configuration array for the dvr test */
+inline void initDvrConfig() {
+ RecordSettings recordSettings{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x07fff,
+ .dataFormat = DataFormat::TS,
+ .packetSize = 188,
+ };
+ dvrArray[DVR_RECORD0].type = DvrType::RECORD;
+ dvrArray[DVR_RECORD0].bufferSize = FMQ_SIZE_4M;
+ dvrArray[DVR_RECORD0].settings.record(recordSettings);
+ PlaybackSettings playbackSettings{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x07fff,
+ .dataFormat = DataFormat::TS,
+ .packetSize = 188,
+ };
+ dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
+ dvrArray[DVR_PLAYBACK0].playbackInputFile = "/vendor/etc/segment000000.ts";
+ dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
+ dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
+};
diff --git a/usb/1.0/default/Android.bp b/usb/1.0/default/Android.bp
index 96d24c1..98d9064 100644
--- a/usb/1.0/default/Android.bp
+++ b/usb/1.0/default/Android.bp
@@ -16,6 +16,7 @@
name: "android.hardware.usb@1.0-service",
defaults: ["hidl_defaults"],
init_rc: ["android.hardware.usb@1.0-service.rc"],
+ vintf_fragments: ["android.hardware.usb@1.0-service.xml"],
relative_install_path: "hw",
vendor: true,
srcs: [
diff --git a/usb/1.0/default/android.hardware.usb@1.0-service.xml b/usb/1.0/default/android.hardware.usb@1.0-service.xml
new file mode 100644
index 0000000..971c872
--- /dev/null
+++ b/usb/1.0/default/android.hardware.usb@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.usb</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IUsb</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/usb/1.0/vts/functional/Android.bp b/usb/1.0/vts/functional/Android.bp
index 1a3b56b..ae31bd2 100644
--- a/usb/1.0/vts/functional/Android.bp
+++ b/usb/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalUsbV1_0TargetTest.cpp"],
static_libs: ["android.hardware.usb@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/usb/1.1/vts/functional/Android.bp b/usb/1.1/vts/functional/Android.bp
index 32c470b..5bec94a 100644
--- a/usb/1.1/vts/functional/Android.bp
+++ b/usb/1.1/vts/functional/Android.bp
@@ -22,6 +22,6 @@
"android.hardware.usb@1.0",
"android.hardware.usb@1.1",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/usb/1.2/vts/functional/Android.bp b/usb/1.2/vts/functional/Android.bp
index 761d37f..d6aaf2d 100644
--- a/usb/1.2/vts/functional/Android.bp
+++ b/usb/1.2/vts/functional/Android.bp
@@ -23,6 +23,8 @@
"android.hardware.usb@1.1",
"android.hardware.usb@1.2",
],
- test_suites: ["general-tests"],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
}
-
diff --git a/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp b/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp
index 7b3dea9..5f901cd 100644
--- a/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp
+++ b/usb/1.2/vts/functional/VtsHalUsbV1_2TargetTest.cpp
@@ -22,8 +22,10 @@
#include <android/hardware/usb/1.2/types.h>
#include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
#include <log/log.h>
#include <stdlib.h>
#include <chrono>
@@ -139,24 +141,12 @@
};
};
-// Test environment for Usb HIDL HAL.
-class UsbHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static UsbHidlEnvironment* Instance() {
- static UsbHidlEnvironment* instance = new UsbHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override { registerTestService<IUsb>(); }
-};
-
// The main test class for the USB hidl HAL
-class UsbHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- public:
+class UsbHidlTest : public ::testing::TestWithParam<std::string> {
+ public:
virtual void SetUp() override {
ALOGI(__FUNCTION__);
- usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>();
+ usb = IUsb::getService(GetParam());
ASSERT_NE(usb, nullptr);
usb_cb_2 = new UsbCallback(kCallbackIdentifier);
@@ -182,7 +172,7 @@
* Callback oject is created and registered.
* Check to see if the hidl transaction succeeded.
*/
-TEST_F(UsbHidlTest, setCallback) {
+TEST_P(UsbHidlTest, setCallback) {
usb_cb_1 = new UsbCallback(1);
ASSERT_NE(usb_cb_1, nullptr);
Return<void> ret = usb->setCallback(usb_cb_1);
@@ -195,7 +185,7 @@
* HAL service should call notifyPortStatusChange_1_2
* instead of notifyPortStatusChange of V1_0/V1_1 interface
*/
-TEST_F(UsbHidlTest, queryPortStatus) {
+TEST_P(UsbHidlTest, queryPortStatus) {
Return<void> ret = usb->queryPortStatus();
ASSERT_TRUE(ret.isOk());
auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
@@ -211,7 +201,7 @@
* Check if supportedContaminantProtectionModes changes across queryPortStatus
* call.
*/
-TEST_F(UsbHidlTest, checkSupportedContaminantProtectionModes) {
+TEST_P(UsbHidlTest, checkSupportedContaminantProtectionModes) {
Return<void> ret = usb->queryPortStatus();
ASSERT_TRUE(ret.isOk());
auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
@@ -243,7 +233,7 @@
* enableContaminantPresenceDetection should not enable/disable
* contaminantPresenceProtection.
*/
-TEST_F(UsbHidlTest, presenceDetectionSupportedCheck) {
+TEST_P(UsbHidlTest, presenceDetectionSupportedCheck) {
Return<void> ret = usb->queryPortStatus();
ASSERT_TRUE(ret.isOk());
auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
@@ -272,7 +262,7 @@
/*
* enableContaminantPresenceDetection should succeed atleast 90% when supported.
*/
-TEST_F(UsbHidlTest, contaminantPresenceDetectionStability) {
+TEST_P(UsbHidlTest, contaminantPresenceDetectionStability) {
int successCount = 0;
bool currentStatus;
bool supported = true;
@@ -309,7 +299,7 @@
* enableContaminantPresenceProtection should not enable/disable
* contaminantPresenceProtection.
*/
-TEST_F(UsbHidlTest, presenceProtectionSupportedCheck) {
+TEST_P(UsbHidlTest, presenceProtectionSupportedCheck) {
Return<void> ret = usb->queryPortStatus();
ASSERT_TRUE(ret.isOk());
auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_2);
@@ -338,7 +328,7 @@
/*
* enableContaminantPresenceProtection should succeed atleast 90% when supported.
*/
-TEST_F(UsbHidlTest, contaminantPresenceProtectionStability) {
+TEST_P(UsbHidlTest, contaminantPresenceProtectionStability) {
int successCount = 0;
bool currentStatus;
bool supported = true;
@@ -370,11 +360,7 @@
if (!supported) EXPECT_GE(successCount, 9);
}
-int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(UsbHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- UsbHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, UsbHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IUsb::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/vibrator/1.0/vts/functional/Android.bp b/vibrator/1.0/vts/functional/Android.bp
index 10ec2cb..4ec1aa8 100644
--- a/vibrator/1.0/vts/functional/Android.bp
+++ b/vibrator/1.0/vts/functional/Android.bp
@@ -19,6 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalVibratorV1_0TargetTest.cpp"],
static_libs: ["android.hardware.vibrator@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/vibrator/1.1/vts/functional/Android.bp b/vibrator/1.1/vts/functional/Android.bp
index 4cde350..b291e7c 100644
--- a/vibrator/1.1/vts/functional/Android.bp
+++ b/vibrator/1.1/vts/functional/Android.bp
@@ -22,6 +22,6 @@
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/vibrator/1.2/vts/functional/Android.bp b/vibrator/1.2/vts/functional/Android.bp
index e7052f2..7bf69d0 100644
--- a/vibrator/1.2/vts/functional/Android.bp
+++ b/vibrator/1.2/vts/functional/Android.bp
@@ -23,6 +23,6 @@
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/vibrator/1.3/vts/functional/Android.bp b/vibrator/1.3/vts/functional/Android.bp
index 038dc5c..5215ed0 100644
--- a/vibrator/1.3/vts/functional/Android.bp
+++ b/vibrator/1.3/vts/functional/Android.bp
@@ -24,6 +24,6 @@
"android.hardware.vibrator@1.2",
"android.hardware.vibrator@1.3",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index ae7f434..9766353 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -15,4 +15,5 @@
},
},
},
+ versions: ["1"],
}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/1/.hash b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/.hash
new file mode 100644
index 0000000..06b7857
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/.hash
@@ -0,0 +1 @@
+eeab78b6096b029f424ab5ce9c2c4ef1249a5cb0
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/CompositeEffect.aidl
new file mode 100644
index 0000000..8cb259f
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/CompositeEffect.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@VintfStability
+parcelable CompositeEffect {
+ int delayMs;
+ android.hardware.vibrator.CompositePrimitive primitive;
+ float scale;
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/CompositePrimitive.aidl
new file mode 100644
index 0000000..6ab7ac5
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/CompositePrimitive.aidl
@@ -0,0 +1,29 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@Backing(type="int") @VintfStability
+enum CompositePrimitive {
+ NOOP = 0,
+ CLICK = 1,
+ THUD = 2,
+ SPIN = 3,
+ QUICK_RISE = 4,
+ SLOW_RISE = 5,
+ QUICK_FALL = 6,
+ LIGHT_TICK = 7,
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/Effect.aidl
new file mode 100644
index 0000000..5ed4dc5
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/Effect.aidl
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@Backing(type="int") @VintfStability
+enum Effect {
+ CLICK = 0,
+ DOUBLE_CLICK = 1,
+ TICK = 2,
+ THUD = 3,
+ POP = 4,
+ HEAVY_CLICK = 5,
+ RINGTONE_1 = 6,
+ RINGTONE_2 = 7,
+ RINGTONE_3 = 8,
+ RINGTONE_4 = 9,
+ RINGTONE_5 = 10,
+ RINGTONE_6 = 11,
+ RINGTONE_7 = 12,
+ RINGTONE_8 = 13,
+ RINGTONE_9 = 14,
+ RINGTONE_10 = 15,
+ RINGTONE_11 = 16,
+ RINGTONE_12 = 17,
+ RINGTONE_13 = 18,
+ RINGTONE_14 = 19,
+ RINGTONE_15 = 20,
+ TEXTURE_TICK = 21,
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/EffectStrength.aidl
new file mode 100644
index 0000000..802d236
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/EffectStrength.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@Backing(type="byte") @VintfStability
+enum EffectStrength {
+ LIGHT = 0,
+ MEDIUM = 1,
+ STRONG = 2,
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/IVibrator.aidl
new file mode 100644
index 0000000..2de1d7b
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/IVibrator.aidl
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@VintfStability
+interface IVibrator {
+ int getCapabilities();
+ void off();
+ void on(in int timeoutMs, in android.hardware.vibrator.IVibratorCallback callback);
+ int perform(in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength, in android.hardware.vibrator.IVibratorCallback callback);
+ android.hardware.vibrator.Effect[] getSupportedEffects();
+ void setAmplitude(in float amplitude);
+ void setExternalControl(in boolean enabled);
+ int getCompositionDelayMax();
+ int getCompositionSizeMax();
+ android.hardware.vibrator.CompositePrimitive[] getSupportedPrimitives();
+ int getPrimitiveDuration(android.hardware.vibrator.CompositePrimitive primitive);
+ void compose(in android.hardware.vibrator.CompositeEffect[] composite, in android.hardware.vibrator.IVibratorCallback callback);
+ android.hardware.vibrator.Effect[] getSupportedAlwaysOnEffects();
+ void alwaysOnEnable(in int id, in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength);
+ void alwaysOnDisable(in int id);
+ const int CAP_ON_CALLBACK = 1;
+ const int CAP_PERFORM_CALLBACK = 2;
+ const int CAP_AMPLITUDE_CONTROL = 4;
+ const int CAP_EXTERNAL_CONTROL = 8;
+ const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 16;
+ const int CAP_COMPOSE_EFFECTS = 32;
+ const int CAP_ALWAYS_ON_CONTROL = 64;
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/IVibratorCallback.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/IVibratorCallback.aidl
new file mode 100644
index 0000000..3a1e7d8
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/1/android/hardware/vibrator/IVibratorCallback.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@VintfStability
+interface IVibratorCallback {
+ oneway void onComplete();
+}
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index d1e135e..28cb4d9 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -13,6 +13,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/vr/1.0/vts/functional/Android.bp b/vr/1.0/vts/functional/Android.bp
index bd0336c..6bfa05c 100644
--- a/vr/1.0/vts/functional/Android.bp
+++ b/vr/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalVrV1_0TargetTest.cpp"],
static_libs: ["android.hardware.vr@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/weaver/1.0/vts/functional/Android.bp b/weaver/1.0/vts/functional/Android.bp
index 3942deb..b20f127 100644
--- a/weaver/1.0/vts/functional/Android.bp
+++ b/weaver/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalWeaverV1_0TargetTest.cpp"],
static_libs: ["android.hardware.weaver@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 2242510..793dd8c 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -51,7 +51,7 @@
"android.hardware.wifi@1.3",
"libwifi-system-iface"
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
// These tests are split out so that they can be conditioned on presence of the
@@ -68,7 +68,7 @@
"android.hardware.wifi@1.0",
"libwifi-system-iface"
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
// These tests are split out so that they can be conditioned on presence of
@@ -85,5 +85,5 @@
"android.hardware.wifi@1.0",
"libwifi-system-iface"
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/1.0/vts/functional/wifi_hidl_call_util.h b/wifi/1.0/vts/functional/wifi_hidl_call_util.h
index f3ca517..3be14c3 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_call_util.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_call_util.h
@@ -16,13 +16,12 @@
#pragma once
+#include <gtest/gtest.h>
#include <functional>
#include <tuple>
#include <type_traits>
#include <utility>
-#include <VtsHalHidlTargetTestBase.h>
-
namespace {
namespace detail {
template <typename>
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index c1542dc..3ff33a5 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -16,8 +16,6 @@
#include <android/log.h>
-#include <VtsHalHidlTargetTestBase.h>
-
#include <wifi_system/interface_tool.h>
#include "wifi_hidl_call_util.h"
diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
index 7db0526..e311c84 100644
--- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -260,8 +260,8 @@
/*
* SetScanningMacOui:
- * Ensures that calls to set scanning MAC OUI will return a success status
- * code.
+ * Ensures that calls to set scanning MAC OUI will return a NOT_SUPPORTED
+ * code since it is now deprecated.
*/
TEST_P(WifiStaIfaceHidlTest, SetScanningMacOui) {
if (!isCapabilitySupported(
@@ -271,7 +271,7 @@
}
const android::hardware::hidl_array<uint8_t, 3> kOui{
std::array<uint8_t, 3>{{0x10, 0x22, 0x33}}};
- EXPECT_EQ(WifiStatusCode::SUCCESS,
+ EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
HIDL_INVOKE(wifi_sta_iface_, setScanningMacOui, kOui).code);
}
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index d34ae22..eb68bc0 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -27,5 +27,5 @@
"android.hardware.wifi@1.3",
"libwifi-system-iface"
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index d3de5cf..90bcac1 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -30,7 +30,7 @@
"libwifi-system-iface"
],
disable_framework: true,
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
cc_test {
@@ -47,5 +47,5 @@
"libwifi-system-iface"
],
disable_framework: true,
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp
index 457de29..3568330 100644
--- a/wifi/1.3/vts/functional/Android.bp
+++ b/wifi/1.3/vts/functional/Android.bp
@@ -30,5 +30,5 @@
"libwifi-system-iface"
],
disable_framework: true,
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/1.4/default/Android.mk b/wifi/1.4/default/Android.mk
index ab76ff6..6be7dad 100644
--- a/wifi/1.4/default/Android.mk
+++ b/wifi/1.4/default/Android.mk
@@ -36,6 +36,9 @@
ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
endif
+ifdef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+LOCAL_CPPFLAGS += -DWIFI_AVOID_IFACE_RESET_MAC_CHANGE
+endif
# Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
LOCAL_SRC_FILES := \
@@ -156,6 +159,11 @@
LOCAL_STATIC_LIBRARIES := \
libgmock \
libgtest \
+ android.hardware.wifi@1.0 \
+ android.hardware.wifi@1.1 \
+ android.hardware.wifi@1.2 \
+ android.hardware.wifi@1.3 \
+ android.hardware.wifi@1.4 \
android.hardware.wifi@1.0-service-lib
LOCAL_SHARED_LIBRARIES := \
libbase \
@@ -165,10 +173,5 @@
libnl \
libutils \
libwifi-hal \
- libwifi-system-iface \
- android.hardware.wifi@1.0 \
- android.hardware.wifi@1.1 \
- android.hardware.wifi@1.2 \
- android.hardware.wifi@1.3 \
- android.hardware.wifi@1.4
+ libwifi-system-iface
include $(BUILD_NATIVE_TEST)
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc b/wifi/1.4/default/android.hardware.wifi@1.0-service.rc
index 2317bac..64a51b0 100644
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.4/default/android.hardware.wifi@1.0-service.rc
@@ -2,6 +2,8 @@
interface android.hardware.wifi@1.0::IWifi default
interface android.hardware.wifi@1.1::IWifi default
interface android.hardware.wifi@1.2::IWifi default
+ interface android.hardware.wifi@1.3::IWifi default
+ interface android.hardware.wifi@1.4::IWifi default
class hal
capabilities NET_ADMIN NET_RAW SYS_MODULE
user wifi
diff --git a/wifi/1.4/default/tests/mock_wifi_iface_util.h b/wifi/1.4/default/tests/mock_wifi_iface_util.h
index 6cc81e4..3b36f13 100644
--- a/wifi/1.4/default/tests/mock_wifi_iface_util.h
+++ b/wifi/1.4/default/tests/mock_wifi_iface_util.h
@@ -40,6 +40,7 @@
MOCK_METHOD2(registerIfaceEventHandlers,
void(const std::string&, IfaceEventHandlers));
MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
+ MOCK_METHOD2(setUpState, bool(const std::string&, bool));
};
} // namespace iface_util
} // namespace implementation
diff --git a/wifi/1.4/default/tests/mock_wifi_legacy_hal.h b/wifi/1.4/default/tests/mock_wifi_legacy_hal.h
index 6942c1e..3bb7b54 100644
--- a/wifi/1.4/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.4/default/tests/mock_wifi_legacy_hal.h
@@ -57,6 +57,10 @@
MOCK_METHOD3(nanDataInterfaceDelete,
wifi_error(const std::string&, transaction_id,
const std::string&));
+ MOCK_METHOD2(createVirtualInterface,
+ wifi_error(const std::string& ifname,
+ wifi_interface_type iftype));
+ MOCK_METHOD1(deleteVirtualInterface, wifi_error(const std::string& ifname));
};
} // namespace legacy_hal
} // namespace implementation
diff --git a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
index d35adbc..d5b1a50 100644
--- a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
@@ -292,6 +292,7 @@
// mock).
property_set("wifi.interface", "wlan0");
property_set("wifi.concurrent.interface", "wlan1");
+ property_set("wifi.aware.interface", nullptr);
}
};
@@ -773,6 +774,28 @@
});
}
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithSharedNanIface) {
+ property_set("wifi.aware.interface", nullptr);
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
+ removeIface(IfaceType::NAN, "wlan0");
+ EXPECT_CALL(*iface_util_, setUpState(testing::_, testing::_)).Times(0);
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithDedicatedNanIface) {
+ property_set("wifi.aware.interface", "aware0");
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ EXPECT_CALL(*iface_util_, setUpState("aware0", true))
+ .WillOnce(testing::Return(true));
+ ASSERT_EQ(createIface(IfaceType::NAN), "aware0");
+
+ EXPECT_CALL(*iface_util_, setUpState("aware0", false))
+ .WillOnce(testing::Return(true));
+ removeIface(IfaceType::NAN, "aware0");
+}
+
////////// V1 Iface Combinations when AP creation is disabled //////////
class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
public:
diff --git a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
index 9022792..70424db 100644
--- a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
+++ b/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -131,7 +131,7 @@
bind(CaptureIfaceEventHandlers, std::placeholders::_1,
std::placeholders::_2, &captured_iface_event_handlers)));
sp<WifiNanIface> nan_iface =
- new WifiNanIface(kIfaceName, legacy_hal_, iface_util_);
+ new WifiNanIface(kIfaceName, false, legacy_hal_, iface_util_);
// Register a mock nan event callback.
sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 4c9fad1..61912a5 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -101,12 +101,31 @@
return "wlan" + std::to_string(idx);
}
+// Returns the dedicated iface name if one is defined.
+std::string getApIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) ==
+ 0) {
+ return {};
+ }
+ return buffer.data();
+}
+
std::string getP2pIfaceName() {
std::array<char, PROPERTY_VALUE_MAX> buffer;
property_get("wifi.direct.interface", buffer.data(), "p2p0");
return buffer.data();
}
+// Returns the dedicated iface name if one is defined.
+std::string getNanIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) {
+ return {};
+ }
+ return buffer.data();
+}
+
void setActiveWlanIfaceNameProperty(const std::string& ifname) {
auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data());
if (res != 0) {
@@ -864,9 +883,16 @@
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
- // These are still assumed to be based on wlan0.
- std::string ifname = getFirstActiveWlanIfaceName();
- sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_, iface_util_);
+ bool is_dedicated_iface = true;
+ std::string ifname = getNanIfaceName();
+ if (ifname.empty()) {
+ // Use the first shared STA iface (wlan0) if a dedicated aware iface is
+ // not defined.
+ ifname = getFirstActiveWlanIfaceName();
+ is_dedicated_iface = false;
+ }
+ sp<WifiNanIface> iface =
+ new WifiNanIface(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
nan_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
@@ -1298,13 +1324,18 @@
LOG(ERROR) << "Error converting ring buffer status";
return;
}
- const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
- if (target != shared_ptr_this->ringbuffer_map_.end()) {
- Ringbuffer& cur_buffer = target->second;
- cur_buffer.append(data);
- } else {
- LOG(ERROR) << "Ringname " << name << " not found";
- return;
+ {
+ std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t);
+ const auto& target =
+ shared_ptr_this->ringbuffer_map_.find(name);
+ if (target != shared_ptr_this->ringbuffer_map_.end()) {
+ Ringbuffer& cur_buffer = target->second;
+ cur_buffer.append(data);
+ } else {
+ LOG(ERROR) << "Ringname " << name << " not found";
+ return;
+ }
+ // unlock
}
};
legacy_hal::wifi_error legacy_status =
@@ -1561,6 +1592,11 @@
// AP iface names start with idx 1 for modes supporting
// concurrent STA and not dual AP, else start with idx 0.
std::string WifiChip::allocateApIfaceName() {
+ // Check if we have a dedicated iface for AP.
+ std::string ifname = getApIfaceName();
+ if (!ifname.empty()) {
+ return ifname;
+ }
return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() &&
!isDualApAllowedInCurrentMode())
? 1
@@ -1579,25 +1615,29 @@
return false;
}
// write ringbuffers to file
- for (const auto& item : ringbuffer_map_) {
- const Ringbuffer& cur_buffer = item.second;
- if (cur_buffer.getData().empty()) {
- continue;
- }
- const std::string file_path_raw =
- kTombstoneFolderPath + item.first + "XXXXXXXXXX";
- const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
- if (dump_fd == -1) {
- PLOG(ERROR) << "create file failed";
- return false;
- }
- unique_fd file_auto_closer(dump_fd);
- for (const auto& cur_block : cur_buffer.getData()) {
- if (write(dump_fd, cur_block.data(),
- sizeof(cur_block[0]) * cur_block.size()) == -1) {
- PLOG(ERROR) << "Error writing to file";
+ {
+ std::unique_lock<std::mutex> lk(lock_t);
+ for (const auto& item : ringbuffer_map_) {
+ const Ringbuffer& cur_buffer = item.second;
+ if (cur_buffer.getData().empty()) {
+ continue;
+ }
+ const std::string file_path_raw =
+ kTombstoneFolderPath + item.first + "XXXXXXXXXX";
+ const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
+ if (dump_fd == -1) {
+ PLOG(ERROR) << "create file failed";
+ return false;
+ }
+ unique_fd file_auto_closer(dump_fd);
+ for (const auto& cur_block : cur_buffer.getData()) {
+ if (write(dump_fd, cur_block.data(),
+ sizeof(cur_block[0]) * cur_block.size()) == -1) {
+ PLOG(ERROR) << "Error writing to file";
+ }
}
}
+ // unlock
}
return true;
}
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.4/default/wifi_chip.h
index 3323ade..98e18bb 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.4/default/wifi_chip.h
@@ -19,6 +19,7 @@
#include <list>
#include <map>
+#include <mutex>
#include <android-base/macros.h>
#include <android/hardware/wifi/1.4/IWifiChip.h>
@@ -272,6 +273,7 @@
bool is_valid_;
// Members pertaining to chip configuration.
uint32_t current_mode_id_;
+ std::mutex lock_t;
std::vector<IWifiChip::ChipMode> modes_;
// The legacy ring buffer callback API has only a global callback
// registration mechanism. Use this to check if we have already
diff --git a/wifi/1.4/default/wifi_iface_util.cpp b/wifi/1.4/default/wifi_iface_util.cpp
index 2883b46..13ba022 100644
--- a/wifi/1.4/default/wifi_iface_util.cpp
+++ b/wifi/1.4/default/wifi_iface_util.cpp
@@ -52,18 +52,22 @@
bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
const std::array<uint8_t, 6>& mac) {
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
LOG(ERROR) << "SetUpState(false) failed.";
return false;
}
+#endif
if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) {
LOG(ERROR) << "SetMacAddress failed.";
return false;
}
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
LOG(ERROR) << "SetUpState(true) failed.";
return false;
}
+#endif
IfaceEventHandlers event_handlers = {};
const auto it = event_handlers_map_.find(iface_name);
if (it != event_handlers_map_.end()) {
@@ -110,6 +114,14 @@
address[0] &= ~kMacAddressMulticastMask;
return address;
}
+
+bool WifiIfaceUtil::setUpState(const std::string& iface_name, bool request_up) {
+ if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), request_up)) {
+ LOG(ERROR) << "SetUpState to " << request_up << " failed";
+ return false;
+ }
+ return true;
+}
} // namespace iface_util
} // namespace implementation
} // namespace V1_4
diff --git a/wifi/1.4/default/wifi_iface_util.h b/wifi/1.4/default/wifi_iface_util.h
index 35edff6..f83d717 100644
--- a/wifi/1.4/default/wifi_iface_util.h
+++ b/wifi/1.4/default/wifi_iface_util.h
@@ -56,6 +56,7 @@
virtual void registerIfaceEventHandlers(const std::string& iface_name,
IfaceEventHandlers handlers);
virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
+ virtual bool setUpState(const std::string& iface_name, bool request_up);
private:
std::array<uint8_t, 6> createRandomMacAddress();
diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.4/default/wifi_legacy_hal.cpp
index f596195..29123bf 100644
--- a/wifi/1.4/default/wifi_legacy_hal.cpp
+++ b/wifi/1.4/default/wifi_legacy_hal.cpp
@@ -801,13 +801,6 @@
cmd_id, getIfaceHandle(iface_name));
}
-wifi_error WifiLegacyHal::setScanningMacOui(const std::string& iface_name,
- const std::array<uint8_t, 3>& oui) {
- std::vector<uint8_t> oui_internal(oui.data(), oui.data() + oui.size());
- return global_func_table_.wifi_set_scanning_mac_oui(
- getIfaceHandle(iface_name), oui_internal.data());
-}
-
wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name,
wifi_power_scenario scenario) {
return global_func_table_.wifi_select_tx_power_scenario(
diff --git a/wifi/1.4/default/wifi_legacy_hal.h b/wifi/1.4/default/wifi_legacy_hal.h
index c21563e..9964460 100644
--- a/wifi/1.4/default/wifi_legacy_hal.h
+++ b/wifi/1.4/default/wifi_legacy_hal.h
@@ -252,8 +252,6 @@
const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms);
wifi_error stopSendingOffloadedPacket(const std::string& iface_name,
uint32_t cmd_id);
- wifi_error setScanningMacOui(const std::string& iface_name,
- const std::array<uint8_t, 3>& oui);
virtual wifi_error selectTxPowerScenario(const std::string& iface_name,
wifi_power_scenario scenario);
virtual wifi_error resetTxPowerScenario(const std::string& iface_name);
@@ -373,9 +371,9 @@
std::array<int8_t, 2> code);
// interface functions.
- wifi_error createVirtualInterface(const std::string& ifname,
- wifi_interface_type iftype);
- wifi_error deleteVirtualInterface(const std::string& ifname);
+ virtual wifi_error createVirtualInterface(const std::string& ifname,
+ wifi_interface_type iftype);
+ virtual wifi_error deleteVirtualInterface(const std::string& ifname);
private:
// Retrieve interface handles for all the available interfaces.
diff --git a/wifi/1.4/default/wifi_nan_iface.cpp b/wifi/1.4/default/wifi_nan_iface.cpp
index 073101c..5764d35 100644
--- a/wifi/1.4/default/wifi_nan_iface.cpp
+++ b/wifi/1.4/default/wifi_nan_iface.cpp
@@ -29,13 +29,22 @@
using hidl_return_util::validateAndCall;
WifiNanIface::WifiNanIface(
- const std::string& ifname,
+ const std::string& ifname, bool is_dedicated_iface,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
: ifname_(ifname),
+ is_dedicated_iface_(is_dedicated_iface),
legacy_hal_(legacy_hal),
iface_util_(iface_util),
is_valid_(true) {
+ if (is_dedicated_iface_) {
+ // If using a dedicated iface, set the iface up first.
+ if (!iface_util_.lock()->setUpState(ifname_, true)) {
+ // Fatal failure, invalidate the iface object.
+ invalidate();
+ return;
+ }
+ }
// Register all the callbacks here. these should be valid for the lifetime
// of the object. Whenever the mode changes legacy HAL will remove
// all of these callbacks.
@@ -534,6 +543,10 @@
event_cb_handler_.invalidate();
event_cb_handler_1_2_.invalidate();
is_valid_ = false;
+ if (is_dedicated_iface_) {
+ // If using a dedicated iface, set the iface down.
+ iface_util_.lock()->setUpState(ifname_, false);
+ }
}
bool WifiNanIface::isValid() { return is_valid_; }
diff --git a/wifi/1.4/default/wifi_nan_iface.h b/wifi/1.4/default/wifi_nan_iface.h
index c16628b..06edbf2 100644
--- a/wifi/1.4/default/wifi_nan_iface.h
+++ b/wifi/1.4/default/wifi_nan_iface.h
@@ -38,7 +38,7 @@
*/
class WifiNanIface : public V1_4::IWifiNanIface {
public:
- WifiNanIface(const std::string& ifname,
+ WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
// Refer to |WifiChip::invalidate()|.
@@ -165,6 +165,7 @@
std::set<sp<V1_2::IWifiNanIfaceEventCallback>> getEventCallbacks_1_2();
std::string ifname_;
+ bool is_dedicated_iface_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
bool is_valid_;
diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.4/default/wifi_sta_iface.cpp
index e2ea6e4..49f383a 100644
--- a/wifi/1.4/default/wifi_sta_iface.cpp
+++ b/wifi/1.4/default/wifi_sta_iface.cpp
@@ -578,10 +578,9 @@
}
WifiStatus WifiStaIface::setScanningMacOuiInternal(
- const std::array<uint8_t, 3>& oui) {
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->setScanningMacOui(ifname_, oui);
- return createWifiStatusFromLegacyError(legacy_status);
+ const std::array<uint8_t, 3>& /* oui */) {
+ // deprecated.
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
}
WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index 7e74cbd..3824c3a 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -35,6 +35,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 726470c..4035fb8 100644
--- a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -64,6 +64,14 @@
wifi_rtt_controller_ = getWifiRttController();
ASSERT_NE(nullptr, wifi_rtt_controller_.get());
+
+ // Check RTT support before we run the test.
+ std::pair<WifiStatus, RttCapabilities> status_and_caps;
+ status_and_caps =
+ HIDL_INVOKE(wifi_rtt_controller_, getCapabilities_1_4);
+ if (status_and_caps.first.code == WifiStatusCode::ERROR_NOT_SUPPORTED) {
+ GTEST_SKIP() << "Skipping this test since RTT is not supported.";
+ }
}
virtual void TearDown() override { stopWifi(GetInstanceName()); }
@@ -140,6 +148,18 @@
* rangeRequest_1_4
*/
TEST_P(WifiRttControllerHidlTest, RangeRequest_1_4) {
+ std::pair<WifiStatus, RttCapabilities> status_and_caps;
+
+ // Get the Capabilities
+ status_and_caps = HIDL_INVOKE(wifi_rtt_controller_, getCapabilities_1_4);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+ // Get the highest support preamble
+ int preamble = 1;
+ status_and_caps.second.preambleSupport >>= 1;
+ while (status_and_caps.second.preambleSupport != 0) {
+ status_and_caps.second.preambleSupport >>= 1;
+ preamble <<= 1;
+ }
std::vector<RttConfig> configs;
RttConfig config;
int cmdId = 55;
@@ -148,13 +168,13 @@
config.addr[i] = i;
}
config.type = RttType::ONE_SIDED;
- config.peer = RttPeerType::STA;
+ config.peer = RttPeerType::AP;
config.channel.width = WifiChannelWidthInMhz::WIDTH_80;
config.channel.centerFreq = 5765;
config.channel.centerFreq0 = 5775;
config.channel.centerFreq1 = 0;
config.bw = RttBw::BW_80MHZ;
- config.preamble = RttPreamble::HE;
+ config.preamble = (RttPreamble)preamble;
config.mustRequestLci = false;
config.mustRequestLcr = false;
config.burstPeriod = 0;
diff --git a/wifi/hostapd/1.0/vts/functional/Android.bp b/wifi/hostapd/1.0/vts/functional/Android.bp
index e966d7e..2a35f15 100644
--- a/wifi/hostapd/1.0/vts/functional/Android.bp
+++ b/wifi/hostapd/1.0/vts/functional/Android.bp
@@ -48,5 +48,5 @@
"libwifi-system",
"libwifi-system-iface",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index 6058fd2..d4063fe 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
@@ -148,4 +147,4 @@
sp<::android::hardware::wifi::hostapd::V1_1::IHostapd> hostapd_1_1 =
::android::hardware::wifi::hostapd::V1_1::IHostapd::castFrom(hostapd);
return hostapd_1_1.get() != nullptr;
-}
\ No newline at end of file
+}
diff --git a/wifi/hostapd/1.1/vts/functional/Android.bp b/wifi/hostapd/1.1/vts/functional/Android.bp
index 8670f2f..291eceb 100644
--- a/wifi/hostapd/1.1/vts/functional/Android.bp
+++ b/wifi/hostapd/1.1/vts/functional/Android.bp
@@ -30,6 +30,6 @@
"libwifi-system",
"libwifi-system-iface",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/hostapd/1.2/vts/functional/Android.bp b/wifi/hostapd/1.2/vts/functional/Android.bp
index 4f4a741..cec1782 100644
--- a/wifi/hostapd/1.2/vts/functional/Android.bp
+++ b/wifi/hostapd/1.2/vts/functional/Android.bp
@@ -31,6 +31,6 @@
"libwifi-system",
"libwifi-system-iface",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/offload/1.0/vts/functional/Android.bp b/wifi/offload/1.0/vts/functional/Android.bp
index 965c946..abfefa8 100644
--- a/wifi/offload/1.0/vts/functional/Android.bp
+++ b/wifi/offload/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalWifiOffloadV1_0TargetTest.cpp"],
static_libs: ["android.hardware.wifi.offload@1.0"],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: ["general-tests", "vts"],
}
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
index a05cc6b..6f282bb 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.bp
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -54,7 +54,7 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
@@ -77,6 +77,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 6fe6fc5..3815323 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <cutils/properties.h>
diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp
index 90a3e87..44b020e 100644
--- a/wifi/supplicant/1.1/vts/functional/Android.bp
+++ b/wifi/supplicant/1.1/vts/functional/Android.bp
@@ -55,6 +55,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/wifi/supplicant/1.2/vts/functional/Android.bp b/wifi/supplicant/1.2/vts/functional/Android.bp
index 80f3658..c23585a 100644
--- a/wifi/supplicant/1.2/vts/functional/Android.bp
+++ b/wifi/supplicant/1.2/vts/functional/Android.bp
@@ -59,7 +59,7 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
@@ -85,6 +85,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.cpp
index 480929a..46d5a61 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include "supplicant_hidl_test_utils.h"
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 2b63ad0..7b96b87 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -16,8 +16,6 @@
#include <android-base/logging.h>
-#include <VtsHalHidlTargetTestBase.h>
-
#include <VtsCoreUtil.h>
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/supplicant/1.2/ISupplicantP2pIface.h>
diff --git a/wifi/supplicant/1.3/vts/functional/Android.bp b/wifi/supplicant/1.3/vts/functional/Android.bp
index 00a0bf7..8eebed0 100644
--- a/wifi/supplicant/1.3/vts/functional/Android.bp
+++ b/wifi/supplicant/1.3/vts/functional/Android.bp
@@ -62,6 +62,6 @@
],
test_suites: [
"general-tests",
- "vts-core",
+ "vts",
],
}
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 dbf2b91..424c107 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
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include "supplicant_hidl_test_utils.h"