From 26d1bc8a4e6c9ae22b2ae2ec614ba578e90a5ec9 Mon Sep 17 00:00:00 2001 From: Lev Proleev Date: Fri, 30 Aug 2019 11:57:18 +0100 Subject: [PATCH] Modify NNAPI VTS tests to run on version 1.3 Bug: 139120468 Test: VtsHalNeuralnetworksV1_3TargetTest Change-Id: I4654dc75c17f8801103015dc1da91663dfa28d52 Merged-In: I4654dc75c17f8801103015dc1da91663dfa28d52 (cherry picked from commit b49dadfb64d585b768b5bcf4f4a61bd3b93e87d1) --- neuralnetworks/1.2/vts/functional/Android.bp | 19 +- neuralnetworks/1.3/vts/functional/Android.bp | 58 ++++ .../1.3/vts/functional/BasicTests.cpp | 62 +--- .../1.3/vts/functional/Callbacks.cpp | 143 -------- .../functional/CompilationCachingTests.cpp | 13 +- .../vts/functional/GeneratedTestHarness.cpp | 18 +- .../1.3/vts/functional/GeneratedTestHarness.h | 19 +- .../1.3/vts/functional/TestAssertions.cpp | 9 +- .../1.3/vts/functional/ValidateBurst.cpp | 11 +- .../1.3/vts/functional/ValidateModel.cpp | 21 +- .../1.3/vts/functional/ValidateRequest.cpp | 10 +- .../vts/functional/VtsHalNeuralnetworks.cpp | 20 +- .../1.3/vts/functional/VtsHalNeuralnetworks.h | 19 +- .../vts/functional/include/1.2/Callbacks.h | 325 ------------------ 14 files changed, 170 insertions(+), 577 deletions(-) create mode 100644 neuralnetworks/1.3/vts/functional/Android.bp delete mode 100644 neuralnetworks/1.3/vts/functional/Callbacks.cpp delete mode 100644 neuralnetworks/1.3/vts/functional/include/1.2/Callbacks.h diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp index 9c50d36ec5..bdca0e95e0 100644 --- a/neuralnetworks/1.2/vts/functional/Android.bp +++ b/neuralnetworks/1.2/vts/functional/Android.bp @@ -14,12 +14,28 @@ // limitations under the License. // +cc_library_static { + name: "VtsHalNeuralNetworksV1_2Callbacks", + defaults: ["VtsHalTargetTestDefaults"], + export_include_dirs: ["include"], + srcs: [ + "Callbacks.cpp", + ], + static_libs: [ + "android.hardware.neuralnetworks@1.0", + "android.hardware.neuralnetworks@1.1", + "android.hardware.neuralnetworks@1.2", + ], + header_libs: [ + "libbase_headers", + ] +} + cc_test { name: "VtsHalNeuralnetworksV1_2TargetTest", defaults: ["VtsHalTargetTestDefaults"], srcs: [ "BasicTests.cpp", - "Callbacks.cpp", "CompilationCachingTests.cpp", "GeneratedTestHarness.cpp", "TestAssertions.cpp", @@ -45,6 +61,7 @@ cc_test { "libneuralnetworks_generated_test_harness", "libneuralnetworks_utils", "VtsHalNeuralNetworksV1_0_utils", + "VtsHalNeuralNetworksV1_2Callbacks", ], whole_static_libs: [ "neuralnetworks_generated_V1_0_example", diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp new file mode 100644 index 0000000000..90ce852e3e --- /dev/null +++ b/neuralnetworks/1.3/vts/functional/Android.bp @@ -0,0 +1,58 @@ +// +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalNeuralNetworksV1_3TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "BasicTests.cpp", + "CompilationCachingTests.cpp", + "GeneratedTestHarness.cpp", + "TestAssertions.cpp", + "ValidateBurst.cpp", + "ValidateModel.cpp", + "ValidateRequest.cpp", + "VtsHalNeuralnetworks.cpp", + ], + shared_libs: [ + "libfmq", + "libnativewindow", + ], + static_libs: [ + "android.hardware.neuralnetworks@1.0", + "android.hardware.neuralnetworks@1.1", + "android.hardware.neuralnetworks@1.2", + "android.hardware.neuralnetworks@1.3", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "libgmock", + "libhidlmemory", + "libneuralnetworks_generated_test_harness", + "libneuralnetworks_utils", + "VtsHalNeuralNetworksV1_0_utils", + "VtsHalNeuralNetworksV1_2Callbacks", + ], + whole_static_libs: [ + "neuralnetworks_generated_V1_0_example", + "neuralnetworks_generated_V1_1_example", + "neuralnetworks_generated_V1_2_example", + "neuralnetworks_generated_V1_3_example", + ], + header_libs: [ + "libneuralnetworks_headers", + ], + test_suites: ["general-tests"], +} diff --git a/neuralnetworks/1.3/vts/functional/BasicTests.cpp b/neuralnetworks/1.3/vts/functional/BasicTests.cpp index 8e82c5376e..b64dc2f61b 100644 --- a/neuralnetworks/1.3/vts/functional/BasicTests.cpp +++ b/neuralnetworks/1.3/vts/functional/BasicTests.cpp @@ -18,11 +18,14 @@ #include "VtsHalNeuralnetworks.h" -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { using V1_0::DeviceStatus; using V1_0::ErrorStatus; using V1_0::PerformanceInfo; +using V1_2::Constant; +using V1_2::DeviceType; +using V1_2::Extension; // create device test TEST_P(NeuralnetworksHidlTest, CreateDevice) {} @@ -37,7 +40,7 @@ TEST_P(NeuralnetworksHidlTest, StatusTest) { // initialization TEST_P(NeuralnetworksHidlTest, GetCapabilitiesTest) { using OperandPerformance = Capabilities::OperandPerformance; - Return ret = kDevice->getCapabilities_1_2([](ErrorStatus status, + Return ret = kDevice->getCapabilities_1_3([](ErrorStatus status, const Capabilities& capabilities) { EXPECT_EQ(ErrorStatus::NONE, status); @@ -58,57 +61,4 @@ TEST_P(NeuralnetworksHidlTest, GetCapabilitiesTest) { }); EXPECT_TRUE(ret.isOk()); } - -// device version test -TEST_P(NeuralnetworksHidlTest, GetDeviceVersionStringTest) { - Return ret = - kDevice->getVersionString([](ErrorStatus status, const hidl_string& version) { - EXPECT_EQ(ErrorStatus::NONE, status); - EXPECT_LT(0, version.size()); - }); - EXPECT_TRUE(ret.isOk()); -} - -// device type test -TEST_P(NeuralnetworksHidlTest, GetDeviceTypeTest) { - Return ret = kDevice->getType([](ErrorStatus status, DeviceType type) { - EXPECT_EQ(ErrorStatus::NONE, status); - EXPECT_TRUE(type == DeviceType::OTHER || type == DeviceType::CPU || - type == DeviceType::GPU || type == DeviceType::ACCELERATOR); - }); - EXPECT_TRUE(ret.isOk()); -} - -// device supported extensions test -TEST_P(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) { - Return ret = kDevice->getSupportedExtensions( - [](ErrorStatus status, const hidl_vec& extensions) { - EXPECT_EQ(ErrorStatus::NONE, status); - for (auto& extension : extensions) { - std::string extensionName = extension.name; - EXPECT_FALSE(extensionName.empty()); - for (char c : extensionName) { - EXPECT_TRUE(('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || c == '_' || - c == '.') - << "Extension name contains an illegal character: " << c; - } - EXPECT_NE(extensionName.find('.'), std::string::npos) - << "Extension name must start with the reverse domain name of the " - "vendor"; - } - }); - EXPECT_TRUE(ret.isOk()); -} - -// getNumberOfCacheFilesNeeded test -TEST_P(NeuralnetworksHidlTest, getNumberOfCacheFilesNeeded) { - Return ret = kDevice->getNumberOfCacheFilesNeeded( - [](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) { - EXPECT_EQ(ErrorStatus::NONE, status); - EXPECT_LE(numModelCache, - static_cast(Constant::MAX_NUMBER_OF_CACHE_FILES)); - EXPECT_LE(numDataCache, static_cast(Constant::MAX_NUMBER_OF_CACHE_FILES)); - }); - EXPECT_TRUE(ret.isOk()); -} -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional diff --git a/neuralnetworks/1.3/vts/functional/Callbacks.cpp b/neuralnetworks/1.3/vts/functional/Callbacks.cpp deleted file mode 100644 index 3972ad6ff2..0000000000 --- a/neuralnetworks/1.3/vts/functional/Callbacks.cpp +++ /dev/null @@ -1,143 +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. - */ - -#define LOG_TAG "Callbacks" - -#include "1.2/Callbacks.h" - -#include - -#include - -namespace android::hardware::neuralnetworks::V1_2::implementation { - -using V1_0::ErrorStatus; - -constexpr Timing kNoTiming = {.timeOnDevice = std::numeric_limits::max(), - .timeInDriver = std::numeric_limits::max()}; - -// PreparedModelCallback methods begin here - -Return PreparedModelCallback::notify(ErrorStatus errorStatus, - const sp& preparedModel) { - { - std::lock_guard hold(mMutex); - - // quick-return if object has already been notified - if (mNotified) { - return Void(); - } - - // store results and mark as notified - mErrorStatus = errorStatus; - mPreparedModel = preparedModel; - mNotified = true; - } - - mCondition.notify_all(); - return Void(); -} - -Return PreparedModelCallback::notify_1_2(ErrorStatus errorStatus, - const sp& preparedModel) { - return notify(errorStatus, preparedModel); -} - -void PreparedModelCallback::wait() const { - std::unique_lock lock(mMutex); - mCondition.wait(lock, [this] { return mNotified; }); -} - -ErrorStatus PreparedModelCallback::getStatus() const { - wait(); - return mErrorStatus; -} - -sp PreparedModelCallback::getPreparedModel() const { - wait(); - return mPreparedModel; -} - -// ExecutionCallback methods begin here - -Return ExecutionCallback::notify(ErrorStatus errorStatus) { - notifyInternal(errorStatus, {}, kNoTiming); - return Void(); -} - -Return ExecutionCallback::notify_1_2(ErrorStatus errorStatus, - const hidl_vec& outputShapes, - const Timing& timing) { - if (errorStatus == ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) { - // outputShapes must not be empty if OUTPUT_INSUFFICIENT_SIZE. - if (outputShapes.size() == 0) { - LOG(ERROR) << "Notified with empty output shape vector when OUTPUT_INSUFFICIENT_SIZE"; - notifyInternal(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming); - return Void(); - } - } else if (errorStatus != ErrorStatus::NONE) { - // outputShapes must be empty if errorStatus is neither NONE nor OUTPUT_INSUFFICIENT_SIZE. - if (outputShapes.size() != 0) { - LOG(ERROR) << "Notified with non-empty output shape vector when error status is " - "neither NONE nor OUTPUT_INSUFFICIENT_SIZE"; - notifyInternal(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming); - return Void(); - } - } - notifyInternal(errorStatus, outputShapes, timing); - return Void(); -} - -void ExecutionCallback::wait() const { - std::unique_lock lock(mMutex); - mCondition.wait(lock, [this] { return mNotified; }); -} - -ErrorStatus ExecutionCallback::getStatus() const { - wait(); - return mErrorStatus; -} - -const std::vector& ExecutionCallback::getOutputShapes() const { - wait(); - return mOutputShapes; -} - -Timing ExecutionCallback::getTiming() const { - wait(); - return mTiming; -} - -void ExecutionCallback::notifyInternal(ErrorStatus errorStatus, - const hidl_vec& outputShapes, - const Timing& timing) { - { - std::lock_guard hold(mMutex); - - // quick-return if object has already been notified - if (mNotified) { - return; - } - - mErrorStatus = errorStatus; - mOutputShapes = outputShapes; - mTiming = timing; - mNotified = true; - } - mCondition.notify_all(); -} - -} // namespace android::hardware::neuralnetworks::V1_2::implementation diff --git a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp index 2130a76b75..0ac4738fff 100644 --- a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp +++ b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp @@ -45,12 +45,15 @@ namespace generated_tests::mobilenet_quantized { const test_helper::TestModel& get_test_model(); } // namespace generated_tests::mobilenet_quantized -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { using namespace test_helper; -using implementation::PreparedModelCallback; using V1_0::ErrorStatus; using V1_1::ExecutionPreference; +using V1_2::Constant; +using V1_2::IPreparedModel; +using V1_2::OperationType; +using V1_2::implementation::PreparedModelCallback; namespace float32_model { @@ -302,7 +305,7 @@ class CompilationCachingTestBase : public testing::Test { // See if the service can handle the model. bool isModelFullySupported(const Model& model) { bool fullySupportsModel = false; - Return supportedCall = kDevice->getSupportedOperations_1_2( + Return supportedCall = kDevice->getSupportedOperations_1_3( model, [&fullySupportsModel, &model](ErrorStatus status, const hidl_vec& supported) { ASSERT_EQ(ErrorStatus::NONE, status); @@ -323,7 +326,7 @@ class CompilationCachingTestBase : public testing::Test { sp preparedModelCallback = new PreparedModelCallback(); hidl_array cacheToken(mToken); Return prepareLaunchStatus = - kDevice->prepareModel_1_2(model, ExecutionPreference::FAST_SINGLE_ANSWER, + kDevice->prepareModel_1_3(model, ExecutionPreference::FAST_SINGLE_ANSWER, modelCache, dataCache, cacheToken, preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(static_cast(prepareLaunchStatus), ErrorStatus::NONE); @@ -1371,4 +1374,4 @@ INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest, testing::Range(0U, 10U)), printCompilationCachingSecurityTest); -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp index 2beec983e0..16a7d70fb5 100644 --- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -44,17 +47,24 @@ #include "Utils.h" #include "VtsHalNeuralnetworks.h" -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { using namespace test_helper; using hidl::memory::V1_0::IMemory; -using implementation::ExecutionCallback; -using implementation::PreparedModelCallback; using V1_0::DataLocation; using V1_0::ErrorStatus; using V1_0::OperandLifeTime; using V1_0::Request; using V1_1::ExecutionPreference; +using V1_2::Constant; +using V1_2::IPreparedModel; +using V1_2::MeasureTiming; +using V1_2::OperationType; +using V1_2::OutputShape; +using V1_2::SymmPerChannelQuantParams; +using V1_2::Timing; +using V1_2::implementation::ExecutionCallback; +using V1_2::implementation::PreparedModelCallback; using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT }; @@ -405,4 +415,4 @@ INSTANTIATE_GENERATED_TEST(GeneratedTest, INSTANTIATE_GENERATED_TEST(DynamicOutputShapeTest, [](const TestModel& testModel) { return !testModel.expectFailure; }); -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h index dfc980c169..b9277cfd4a 100644 --- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h +++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h @@ -14,19 +14,19 @@ * limitations under the License. */ -#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H -#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H +#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_3_GENERATED_TEST_HARNESS_H +#define ANDROID_HARDWARE_NEURALNETWORKS_V1_3_GENERATED_TEST_HARNESS_H -#include #include -#include +#include +#include #include #include #include "1.0/Utils.h" #include "TestHarness.h" #include "VtsHalNeuralnetworks.h" -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { using NamedModel = Named; using GeneratedTestParam = std::tuple; @@ -55,11 +55,12 @@ class ValidationTest : public GeneratedTestBase {}; Model createModel(const test_helper::TestModel& testModel); -void PrepareModel(const sp& device, const Model& model, sp* preparedModel); +void PrepareModel(const sp& device, const Model& model, + sp* preparedModel); -void EvaluatePreparedModel(const sp& preparedModel, +void EvaluatePreparedModel(const sp& preparedModel, const test_helper::TestModel& testModel, bool testDynamicOutputShape); -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional -#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H +#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_3_GENERATED_TEST_HARNESS_H diff --git a/neuralnetworks/1.3/vts/functional/TestAssertions.cpp b/neuralnetworks/1.3/vts/functional/TestAssertions.cpp index a0aa3c37d1..7361078eca 100644 --- a/neuralnetworks/1.3/vts/functional/TestAssertions.cpp +++ b/neuralnetworks/1.3/vts/functional/TestAssertions.cpp @@ -14,10 +14,10 @@ * limitations under the License. */ -#include +#include #include "TestHarness.h" -namespace android::hardware::neuralnetworks::V1_2 { +namespace android::hardware::neuralnetworks::V1_3 { // Make sure that the HIDL enums are compatible with the values defined in // frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h. @@ -25,6 +25,8 @@ using namespace test_helper; #define CHECK_TEST_ENUM(EnumType, enumValue) \ static_assert(static_cast(Test##EnumType::enumValue) == EnumType::enumValue) +using V1_2::OperationType; + CHECK_TEST_ENUM(OperandType, FLOAT32); CHECK_TEST_ENUM(OperandType, INT32); CHECK_TEST_ENUM(OperandType, UINT32); @@ -39,6 +41,7 @@ CHECK_TEST_ENUM(OperandType, FLOAT16); CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_SYMM_PER_CHANNEL); CHECK_TEST_ENUM(OperandType, TENSOR_QUANT16_ASYMM); CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_SYMM); +CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_ASYMM_SIGNED); CHECK_TEST_ENUM(OperationType, ADD); CHECK_TEST_ENUM(OperationType, AVERAGE_POOL_2D); @@ -138,4 +141,4 @@ CHECK_TEST_ENUM(OperationType, RESIZE_NEAREST_NEIGHBOR); #undef CHECK_TEST_ENUM -} // namespace android::hardware::neuralnetworks::V1_2 +} // namespace android::hardware::neuralnetworks::V1_3 diff --git a/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp index 1d4493d208..95f9f427b2 100644 --- a/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp +++ b/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp @@ -28,13 +28,20 @@ #include #include -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { using nn::ExecutionBurstController; using nn::RequestChannelSender; using nn::ResultChannelReceiver; using V1_0::ErrorStatus; using V1_0::Request; +using V1_2::FmqRequestDatum; +using V1_2::FmqResultDatum; +using V1_2::IBurstCallback; +using V1_2::IBurstContext; +using V1_2::IPreparedModel; +using V1_2::MeasureTiming; +using V1_2::Timing; using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback; // This constant value represents the length of an FMQ that is large enough to @@ -397,4 +404,4 @@ void validateBurst(const sp& preparedModel, const Request& reque ASSERT_NO_FATAL_FAILURE(validateBurstSanitized(preparedModel, request)); } -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp index 30530beacc..44b32a9fec 100644 --- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp @@ -21,21 +21,26 @@ #include "GeneratedTestHarness.h" #include "VtsHalNeuralnetworks.h" -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { -using implementation::PreparedModelCallback; using V1_0::ErrorStatus; using V1_0::OperandLifeTime; using V1_1::ExecutionPreference; -using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; +using V1_2::IPreparedModel; +using V1_2::OperationType; +using V1_2::OperationTypeRange; +using V1_2::SymmPerChannelQuantParams; +using V1_2::implementation::PreparedModelCallback; +using HidlToken = + hidl_array(V1_2::Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; ///////////////////////// UTILITY FUNCTIONS ///////////////////////// static void validateGetSupportedOperations(const sp& device, const std::string& message, const Model& model) { - SCOPED_TRACE(message + " [getSupportedOperations_1_2]"); + SCOPED_TRACE(message + " [getSupportedOperations_1_3]"); - Return ret = device->getSupportedOperations_1_2( + Return ret = device->getSupportedOperations_1_3( model, [&](ErrorStatus status, const hidl_vec&) { EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status); }); @@ -44,11 +49,11 @@ static void validateGetSupportedOperations(const sp& device, const std: static void validatePrepareModel(const sp& device, const std::string& message, const Model& model, ExecutionPreference preference) { - SCOPED_TRACE(message + " [prepareModel_1_2]"); + SCOPED_TRACE(message + " [prepareModel_1_3]"); sp preparedModelCallback = new PreparedModelCallback(); Return prepareLaunchStatus = - device->prepareModel_1_2(model, preference, hidl_vec(), + device->prepareModel_1_3(model, preference, hidl_vec(), hidl_vec(), HidlToken(), preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast(prepareLaunchStatus)); @@ -710,4 +715,4 @@ void validateModel(const sp& device, const Model& model) { mutateExecutionPreferenceTest(device, model); } -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp index f25ee62617..612212382c 100644 --- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp @@ -24,11 +24,15 @@ #include "Utils.h" #include "VtsHalNeuralnetworks.h" -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { -using implementation::ExecutionCallback; using V1_0::ErrorStatus; using V1_0::Request; +using V1_2::IPreparedModel; +using V1_2::MeasureTiming; +using V1_2::OutputShape; +using V1_2::Timing; +using V1_2::implementation::ExecutionCallback; ///////////////////////// UTILITY FUNCTIONS ///////////////////////// @@ -165,4 +169,4 @@ void validateRequestFailure(const sp& preparedModel, const Reque ASSERT_TRUE(executeStatus.isOk()); } -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp index 4fbd0e270f..4f0e150b32 100644 --- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp @@ -26,13 +26,15 @@ #include "GeneratedTestHarness.h" #include "TestHarness.h" -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { -using implementation::PreparedModelCallback; -using HidlToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; +using HidlToken = + hidl_array(V1_2::Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; using V1_0::ErrorStatus; using V1_0::Request; using V1_1::ExecutionPreference; +using V1_2::IPreparedModel; +using V1_2::implementation::PreparedModelCallback; // internal helper function void createPreparedModel(const sp& device, const Model& model, @@ -42,7 +44,7 @@ void createPreparedModel(const sp& device, const Model& model, // see if service can handle model bool fullySupportsModel = false; - const Return supportedCall = device->getSupportedOperations_1_2( + const Return supportedCall = device->getSupportedOperations_1_3( model, [&fullySupportsModel](ErrorStatus status, const hidl_vec& supported) { ASSERT_EQ(ErrorStatus::NONE, status); ASSERT_NE(0ul, supported.size()); @@ -53,7 +55,7 @@ void createPreparedModel(const sp& device, const Model& model, // launch prepare model const sp preparedModelCallback = new PreparedModelCallback(); - const Return prepareLaunchStatus = device->prepareModel_1_2( + const Return prepareLaunchStatus = device->prepareModel_1_3( model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec(), hidl_vec(), HidlToken(), preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); @@ -64,8 +66,8 @@ void createPreparedModel(const sp& device, const Model& model, const ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); *preparedModel = getPreparedModel_1_2(preparedModelCallback); - // The getSupportedOperations_1_2 call returns a list of operations that are - // guaranteed not to fail if prepareModel_1_2 is called, and + // The getSupportedOperations_1_3 call returns a list of operations that are + // guaranteed not to fail if prepareModel_1_3 is called, and // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed. // If a driver has any doubt that it can prepare an operation, it must // return false. So here, if a driver isn't sure if it can support an @@ -163,9 +165,9 @@ TEST_P(ValidationTest, Test) { INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; }); -sp getPreparedModel_1_2(const sp& callback) { +sp getPreparedModel_1_2(const sp& callback) { sp preparedModelV1_0 = callback->getPreparedModel(); return IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr); } -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h index d01336eccd..fc654ce8f0 100644 --- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h +++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h @@ -14,17 +14,17 @@ * limitations under the License. */ -#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H -#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H +#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_3_VTS_HAL_NEURALNETWORKS_H +#define ANDROID_HARDWARE_NEURALNETWORKS_V1_3_VTS_HAL_NEURALNETWORKS_H -#include #include -#include +#include +#include #include #include "1.0/Utils.h" #include "1.2/Callbacks.h" -namespace android::hardware::neuralnetworks::V1_2::vts::functional { +namespace android::hardware::neuralnetworks::V1_3::vts::functional { using NamedDevice = Named>; using NeuralnetworksHidlTestParam = NamedDevice; @@ -47,11 +47,12 @@ std::string printNeuralnetworksHidlTest( // Create an IPreparedModel object. If the model cannot be prepared, // "preparedModel" will be nullptr instead. void createPreparedModel(const sp& device, const Model& model, - sp* preparedModel); + sp* preparedModel); // Utility function to get PreparedModel from callback and downcast to V1_2. -sp getPreparedModel_1_2(const sp& callback); +sp getPreparedModel_1_2( + const sp& callback); -} // namespace android::hardware::neuralnetworks::V1_2::vts::functional +} // namespace android::hardware::neuralnetworks::V1_3::vts::functional -#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H +#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_3_VTS_HAL_NEURALNETWORKS_H diff --git a/neuralnetworks/1.3/vts/functional/include/1.2/Callbacks.h b/neuralnetworks/1.3/vts/functional/include/1.2/Callbacks.h deleted file mode 100644 index bf4792cc6b..0000000000 --- a/neuralnetworks/1.3/vts/functional/include/1.2/Callbacks.h +++ /dev/null @@ -1,325 +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_NEURALNETWORKS_V1_2_CALLBACKS_H -#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * The Callback classes are used internally by the NeuralNetworks runtime to - * synchronize between different threads. An asynchronous task is launched - * paired with a callback object. When a client thread requires the output being - * generated by the asynchronous task, the client thread can wait for the result - * and be blocked until it has completed. Any wait may safely be called - * concurrently, even on the same callback object. When the asynchronous task - * has finished its workload, it must immediately call "notify*". If the - * asynchronous task has failed to launch, the function that tried to launch the - * asynchronous task must immediately call "notify*". This "notify*" call - * awakens any client threads waiting on the callback object. - * - * These classes exist to enable synchronization across HIDL. When - * synchronization is only required in the same process, consider using - * std::future, std::mutex, std::condition_variable, or std::experimental::latch - * instead. - */ - -namespace android::hardware::neuralnetworks::V1_2::implementation { - -/** - * The PreparedModelCallback class is used to receive the error status of - * preparing a model as well as the prepared model from a task executing - * asynchronously with respect to the runtime. If a calling thread calls wait - * or get* on a PreparedModelCallback object and the corresponding asynchronous - * task has not finished preparing the model, the calling thread will block - * until the asynchronous task has either called notify or notify_1_2. - * - * If the callback object is notified more than once, only the results of the - * first call to notify* are used, and the results from subsequent calls are - * discarded. - * - * This callback object is passed as an argument to IDevice::prepareModel*. - */ -class PreparedModelCallback : public IPreparedModelCallback { - public: - /** - * IPreparedModelCallback::notify marks the callback object with the return - * status of the asynchronous model preparation along with the prepared - * model, and allows all prior and future wait calls on the - * PreparedModelCallback object to proceed. - * - * Either IPreparedModelCallback::notify or - * IPreparedModelCallback::notify_1_2 must be called on a given - * PreparedModelCallback object. - * - * If the callback object is notified more than once, only the results of - * the first call to notify* are used, and the results from subsequent calls - * are discarded. - * - * @param status Error status returned from asynchronously preparing the - * model; will be: - * - NONE if the asynchronous preparation was successful - * - DEVICE_UNAVAILABLE if driver is offline or busy - * - GENERAL_FAILURE if there is an unspecified error - * - INVALID_ARGUMENT if the input model is invalid - * @param preparedModel Returned model that has been prepared for execution, - * nullptr if the model was unable to be prepared. - */ - Return notify(V1_0::ErrorStatus status, - const sp& preparedModel) override; - - /** - * IPreparedModelCallback::notify_1_2 marks the callback object with the - * return status of the asynchronous model preparation along with the - * prepared model, and allows all prior and future wait calls on the - * PreparedModelCallback object to proceed. - * - * Either IPreparedModelCallback::notify or - * IPreparedModelCallback::notify_1_2 must be called on a given - * PreparedModelCallback object. - * - * If the callback object is notified more than once, only the results of - * the first call to notify* are used, and the results from subsequent calls - * are discarded. - * - * @param status Error status returned from asynchronously preparing the - * model; will be: - * - NONE if the asynchronous preparation was successful - * - DEVICE_UNAVAILABLE if driver is offline or busy - * - GENERAL_FAILURE if there is an unspecified error - * - INVALID_ARGUMENT if the input model is invalid - * @param preparedModel Returned model that has been prepared for execution, - * nullptr if the model was unable to be prepared. - */ - Return notify_1_2(V1_0::ErrorStatus status, - const sp& preparedModel) override; - - /** - * PreparedModelCallback::wait blocks until notify* has been called on the - * callback object. - */ - void wait() const; - - /** - * Retrieves the error status returned from the asynchronous task launched - * by IDevice::prepareModel*. If IDevice::prepareModel* has not finished - * asynchronously preparing the model, this call will block until the - * asynchronous task notifies the object. - * - * @return status Error status returned from asynchronously preparing the - * model; will be: - * - NONE if the asynchronous preparation was successful - * - DEVICE_UNAVAILABLE if driver is offline or busy - * - GENERAL_FAILURE if there is an unspecified error - * - INVALID_ARGUMENT if the input model is invalid - */ - V1_0::ErrorStatus getStatus() const; - - /** - * Retrieves the model that has been prepared for execution from the - * asynchronous task launched by IDevice::prepareModel*. If - * IDevice::prepareModel* has not finished asynchronously preparing the - * model, this call will block until the asynchronous task notifies the - * object. - * - * @return preparedModel Returned model that has been prepared for - * execution, nullptr if the model was unable to be prepared. - */ - sp getPreparedModel() const; - - private: - mutable std::mutex mMutex; - mutable std::condition_variable mCondition; - bool mNotified GUARDED_BY(mMutex) = false; - V1_0::ErrorStatus mErrorStatus = V1_0::ErrorStatus::GENERAL_FAILURE; - sp mPreparedModel; -}; - -/** - * The ExecutionCallback class is used to receive the results of the execution - * from a task executing asynchronously with respect to the runtime. If a - * calling thread calls wait or get* on a ExecutionCallback object and the - * corresponding asynchronous task has not finished the execution, the calling - * thread will block until the asynchronous task has either called notify or - * notify_1_2. - * - * If the callback object is notified more than once, only the results of the - * first call to notify* are used, and the results from subsequent calls are - * discarded. - * - * This callback object is passed as an argument to IPreparedModel::execute*. - */ -class ExecutionCallback : public IExecutionCallback { - public: - /** - * IExecutionCallback::notify marks the callback object with the return - * status of the asynchronous execution that held this callback and enables - * all prior and future wait calls on the ExecutionCallback object to - * proceed. - * - * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must - * be called on a given ExecutionCallback object. - * - * If the callback object is notified more than once, only the results of - * the first call to notify* are used, and the results from subsequent calls - * are discarded. - * - * @param status Error status returned from launching the asynchronous task - * (if the launch fails) or from the asynchronous task itself (if the - * launch succeeds). Must be: - * - NONE if the asynchronous execution was successful - * - DEVICE_UNAVAILABLE if driver is offline or busy - * - GENERAL_FAILURE if there is an unspecified error - * - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is not large - * enough to store the resultant values - * - INVALID_ARGUMENT if the input request is invalid - */ - Return notify(V1_0::ErrorStatus status) override; - - /** - * IExecutionCallback::notify_1_2 marks the callback object with the results - * (error status, dynamic output shapes, and timing information) of the - * asynchronous execution that held this callback and enables all prior and - * future wait calls on the ExecutionCallback object to proceed. - * - * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must - * be called on a given ExecutionCallback object. - * - * If the callback object is notified more than once, only the results of - * the first call to notify* are used, and the results from subsequent calls - * are discarded. - * - * @param status Error status returned from launching the asynchronous task - * (if the launch fails) or from the asynchronous task itself (if the - * launch succeeds). Must be: - * - NONE if the asynchronous execution was successful - * - DEVICE_UNAVAILABLE if driver is offline or busy - * - GENERAL_FAILURE if the asynchronous task resulted in an unspecified - * error - * - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is - * not large enough to store the corresponding output - * - INVALID_ARGUMENT if one of the input arguments to prepareModel is - * invalid - * @param outputShapes A list of shape information of model output operands. - * The index into "outputShapes" corresponds to the index of the output - * operand in the Request outputs vector. outputShapes must be empty - * unless the status is either NONE or OUTPUT_INSUFFICIENT_SIZE. - * @param Timing Duration of execution. Unless MeasureTiming::YES was passed - * when launching the execution and status is NONE, all times must be - * reported as UINT64_MAX. A driver may choose to report any time as - * UINT64_MAX, indicating that particular measurement is not available. - */ - Return notify_1_2(V1_0::ErrorStatus status, const hidl_vec& outputShapes, - const Timing& timing) override; - - // An overload of the latest notify interface to hide the version from ExecutionBuilder. - Return notify(V1_0::ErrorStatus status, const hidl_vec& outputShapes, - const Timing& timing) { - return notify_1_2(status, outputShapes, timing); - } - - /** - * ExecutionCallback::wait blocks until notify* has been called on the - * callback object. - */ - void wait() const; - - /** - * Retrieves the error status returned from the asynchronous task launched - * by either IPreparedModel::execute or IPreparedModel::execute_1_2. If - * IPreparedModel::execute or IPreparedModel::execute_1_2 has not finished - * asynchronously executing, this call will block until the asynchronous - * task notifies the object. - * - * @return status Error status returned from launching the asynchronous task - * (if the launch fails) or from the asynchronous task itself (if the - * launch succeeds). Must be: - * - NONE if the asynchronous execution was successful - * - DEVICE_UNAVAILABLE if driver is offline or busy - * - GENERAL_FAILURE if the asynchronous task resulted in an unspecified - * error - * - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is - * not large enough to store the corresponding output - * - INVALID_ARGUMENT if one of the input arguments to prepareModel is - * invalid - */ - V1_0::ErrorStatus getStatus() const; - - /** - * Retrieves the output shapes returned from the asynchronous task launched - * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not - * finished asynchronously executing, this call will block until the - * asynchronous task notifies the object. - * - * If the asynchronous task was launched by IPreparedModel::execute, an - * empty vector will be returned. - * - * @return outputShapes A list of shape information of model output - * operands. The index into "outputShapes" corresponds to the index of - * the output operand in the Request outputs vector. outputShapes must - * be empty unless the status is either NONE or - * OUTPUT_INSUFFICIENT_SIZE. outputShaps may be empty if the status is - * NONE and all model output operands are fully-specified at execution - * time. outputShapes must have the same number of elements as the - * number of model output operands if the status is - * OUTPUT_INSUFFICIENT_SIZE, or if the status is NONE and the model has - * at least one output operand that is not fully-specified. - */ - const std::vector& getOutputShapes() const; - - /** - * Retrieves the duration of execution of the asynchronous task launched by - * IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not - * finished asynchronously executing, this call will block until the - * asynchronous task notifies the object. - * - * If the asynchronous task was launched by IPreparedModel::execute, every - * time must be UINT64_MAX. - * - * @return timing Duration of the execution. Every time must be UINT64_MAX - * unless the status is NONE. - */ - Timing getTiming() const; - - private: - /* - * ExecutionCallback::notifyInternal stores the results of the execution - * (status, output shapes, and timing information) in the ExecutionCallback - * object before any call to wait or get* return. It then enables all prior - * and future wait calls on the ExecutionCallback object to proceed. - */ - void notifyInternal(V1_0::ErrorStatus errorStatus, const hidl_vec& outputShapes, - const Timing& timing); - - // members - mutable std::mutex mMutex; - mutable std::condition_variable mCondition; - bool mNotified GUARDED_BY(mMutex) = false; - V1_0::ErrorStatus mErrorStatus = V1_0::ErrorStatus::GENERAL_FAILURE; - std::vector mOutputShapes = {}; - Timing mTiming = {}; -}; - -} // namespace android::hardware::neuralnetworks::V1_2::implementation - -#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H