Loading neuralnetworks/1.3/vts/OWNERS 0 → 100644 +16 −0 Original line number Diff line number Diff line # Neuralnetworks team butlermichael@google.com dgross@google.com jeanluc@google.com levp@google.com miaowang@google.com mikie@google.com mks@google.com pszczepaniak@google.com slavash@google.com vddang@google.com xusongw@google.com # VTS team yim@google.com yuexima@google.com neuralnetworks/1.3/vts/functional/BasicTests.cpp 0 → 100644 +114 −0 Original line number Diff line number Diff line /* * 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. */ #define LOG_TAG "neuralnetworks_hidl_hal_test" #include "VtsHalNeuralnetworks.h" namespace android::hardware::neuralnetworks::V1_2::vts::functional { using V1_0::DeviceStatus; using V1_0::ErrorStatus; using V1_0::PerformanceInfo; // create device test TEST_P(NeuralnetworksHidlTest, CreateDevice) {} // status test TEST_P(NeuralnetworksHidlTest, StatusTest) { Return<DeviceStatus> status = kDevice->getStatus(); ASSERT_TRUE(status.isOk()); EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status)); } // initialization TEST_P(NeuralnetworksHidlTest, GetCapabilitiesTest) { using OperandPerformance = Capabilities::OperandPerformance; Return<void> ret = kDevice->getCapabilities_1_2([](ErrorStatus status, const Capabilities& capabilities) { EXPECT_EQ(ErrorStatus::NONE, status); auto isPositive = [](const PerformanceInfo& perf) { return perf.execTime > 0.0f && perf.powerUsage > 0.0f; }; EXPECT_TRUE(isPositive(capabilities.relaxedFloat32toFloat16PerformanceScalar)); EXPECT_TRUE(isPositive(capabilities.relaxedFloat32toFloat16PerformanceTensor)); const auto& opPerf = capabilities.operandPerformance; EXPECT_TRUE(std::all_of( opPerf.begin(), opPerf.end(), [isPositive](const OperandPerformance& a) { return isPositive(a.info); })); EXPECT_TRUE(std::is_sorted(opPerf.begin(), opPerf.end(), [](const OperandPerformance& a, const OperandPerformance& b) { return a.type < b.type; })); }); EXPECT_TRUE(ret.isOk()); } // device version test TEST_P(NeuralnetworksHidlTest, GetDeviceVersionStringTest) { Return<void> 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<void> 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<void> ret = kDevice->getSupportedExtensions( [](ErrorStatus status, const hidl_vec<Extension>& 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<void> ret = kDevice->getNumberOfCacheFilesNeeded( [](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) { EXPECT_EQ(ErrorStatus::NONE, status); EXPECT_LE(numModelCache, static_cast<uint32_t>(Constant::MAX_NUMBER_OF_CACHE_FILES)); EXPECT_LE(numDataCache, static_cast<uint32_t>(Constant::MAX_NUMBER_OF_CACHE_FILES)); }); EXPECT_TRUE(ret.isOk()); } } // namespace android::hardware::neuralnetworks::V1_2::vts::functional neuralnetworks/1.3/vts/functional/Callbacks.cpp 0 → 100644 +143 −0 Original line number Diff line number Diff line /* * 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 <android-base/logging.h> #include <limits> namespace android::hardware::neuralnetworks::V1_2::implementation { using V1_0::ErrorStatus; constexpr Timing kNoTiming = {.timeOnDevice = std::numeric_limits<uint64_t>::max(), .timeInDriver = std::numeric_limits<uint64_t>::max()}; // PreparedModelCallback methods begin here Return<void> PreparedModelCallback::notify(ErrorStatus errorStatus, const sp<V1_0::IPreparedModel>& preparedModel) { { std::lock_guard<std::mutex> 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<void> PreparedModelCallback::notify_1_2(ErrorStatus errorStatus, const sp<V1_2::IPreparedModel>& preparedModel) { return notify(errorStatus, preparedModel); } void PreparedModelCallback::wait() const { std::unique_lock<std::mutex> lock(mMutex); mCondition.wait(lock, [this] { return mNotified; }); } ErrorStatus PreparedModelCallback::getStatus() const { wait(); return mErrorStatus; } sp<V1_0::IPreparedModel> PreparedModelCallback::getPreparedModel() const { wait(); return mPreparedModel; } // ExecutionCallback methods begin here Return<void> ExecutionCallback::notify(ErrorStatus errorStatus) { notifyInternal(errorStatus, {}, kNoTiming); return Void(); } Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus, const hidl_vec<OutputShape>& 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<std::mutex> lock(mMutex); mCondition.wait(lock, [this] { return mNotified; }); } ErrorStatus ExecutionCallback::getStatus() const { wait(); return mErrorStatus; } const std::vector<OutputShape>& ExecutionCallback::getOutputShapes() const { wait(); return mOutputShapes; } Timing ExecutionCallback::getTiming() const { wait(); return mTiming; } void ExecutionCallback::notifyInternal(ErrorStatus errorStatus, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) { { std::lock_guard<std::mutex> 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 Loading
neuralnetworks/1.3/vts/OWNERS 0 → 100644 +16 −0 Original line number Diff line number Diff line # Neuralnetworks team butlermichael@google.com dgross@google.com jeanluc@google.com levp@google.com miaowang@google.com mikie@google.com mks@google.com pszczepaniak@google.com slavash@google.com vddang@google.com xusongw@google.com # VTS team yim@google.com yuexima@google.com
neuralnetworks/1.3/vts/functional/BasicTests.cpp 0 → 100644 +114 −0 Original line number Diff line number Diff line /* * 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. */ #define LOG_TAG "neuralnetworks_hidl_hal_test" #include "VtsHalNeuralnetworks.h" namespace android::hardware::neuralnetworks::V1_2::vts::functional { using V1_0::DeviceStatus; using V1_0::ErrorStatus; using V1_0::PerformanceInfo; // create device test TEST_P(NeuralnetworksHidlTest, CreateDevice) {} // status test TEST_P(NeuralnetworksHidlTest, StatusTest) { Return<DeviceStatus> status = kDevice->getStatus(); ASSERT_TRUE(status.isOk()); EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status)); } // initialization TEST_P(NeuralnetworksHidlTest, GetCapabilitiesTest) { using OperandPerformance = Capabilities::OperandPerformance; Return<void> ret = kDevice->getCapabilities_1_2([](ErrorStatus status, const Capabilities& capabilities) { EXPECT_EQ(ErrorStatus::NONE, status); auto isPositive = [](const PerformanceInfo& perf) { return perf.execTime > 0.0f && perf.powerUsage > 0.0f; }; EXPECT_TRUE(isPositive(capabilities.relaxedFloat32toFloat16PerformanceScalar)); EXPECT_TRUE(isPositive(capabilities.relaxedFloat32toFloat16PerformanceTensor)); const auto& opPerf = capabilities.operandPerformance; EXPECT_TRUE(std::all_of( opPerf.begin(), opPerf.end(), [isPositive](const OperandPerformance& a) { return isPositive(a.info); })); EXPECT_TRUE(std::is_sorted(opPerf.begin(), opPerf.end(), [](const OperandPerformance& a, const OperandPerformance& b) { return a.type < b.type; })); }); EXPECT_TRUE(ret.isOk()); } // device version test TEST_P(NeuralnetworksHidlTest, GetDeviceVersionStringTest) { Return<void> 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<void> 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<void> ret = kDevice->getSupportedExtensions( [](ErrorStatus status, const hidl_vec<Extension>& 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<void> ret = kDevice->getNumberOfCacheFilesNeeded( [](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) { EXPECT_EQ(ErrorStatus::NONE, status); EXPECT_LE(numModelCache, static_cast<uint32_t>(Constant::MAX_NUMBER_OF_CACHE_FILES)); EXPECT_LE(numDataCache, static_cast<uint32_t>(Constant::MAX_NUMBER_OF_CACHE_FILES)); }); EXPECT_TRUE(ret.isOk()); } } // namespace android::hardware::neuralnetworks::V1_2::vts::functional
neuralnetworks/1.3/vts/functional/Callbacks.cpp 0 → 100644 +143 −0 Original line number Diff line number Diff line /* * 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 <android-base/logging.h> #include <limits> namespace android::hardware::neuralnetworks::V1_2::implementation { using V1_0::ErrorStatus; constexpr Timing kNoTiming = {.timeOnDevice = std::numeric_limits<uint64_t>::max(), .timeInDriver = std::numeric_limits<uint64_t>::max()}; // PreparedModelCallback methods begin here Return<void> PreparedModelCallback::notify(ErrorStatus errorStatus, const sp<V1_0::IPreparedModel>& preparedModel) { { std::lock_guard<std::mutex> 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<void> PreparedModelCallback::notify_1_2(ErrorStatus errorStatus, const sp<V1_2::IPreparedModel>& preparedModel) { return notify(errorStatus, preparedModel); } void PreparedModelCallback::wait() const { std::unique_lock<std::mutex> lock(mMutex); mCondition.wait(lock, [this] { return mNotified; }); } ErrorStatus PreparedModelCallback::getStatus() const { wait(); return mErrorStatus; } sp<V1_0::IPreparedModel> PreparedModelCallback::getPreparedModel() const { wait(); return mPreparedModel; } // ExecutionCallback methods begin here Return<void> ExecutionCallback::notify(ErrorStatus errorStatus) { notifyInternal(errorStatus, {}, kNoTiming); return Void(); } Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus, const hidl_vec<OutputShape>& 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<std::mutex> lock(mMutex); mCondition.wait(lock, [this] { return mNotified; }); } ErrorStatus ExecutionCallback::getStatus() const { wait(); return mErrorStatus; } const std::vector<OutputShape>& ExecutionCallback::getOutputShapes() const { wait(); return mOutputShapes; } Timing ExecutionCallback::getTiming() const { wait(); return mTiming; } void ExecutionCallback::notifyInternal(ErrorStatus errorStatus, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) { { std::lock_guard<std::mutex> 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