summaryrefslogtreecommitdiff
path: root/neuralnetworks/utils/adapter/src/PreparedModel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'neuralnetworks/utils/adapter/src/PreparedModel.cpp')
-rw-r--r--neuralnetworks/utils/adapter/src/PreparedModel.cpp417
1 files changed, 0 insertions, 417 deletions
diff --git a/neuralnetworks/utils/adapter/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/src/PreparedModel.cpp
deleted file mode 100644
index 8968c2cc91..0000000000
--- a/neuralnetworks/utils/adapter/src/PreparedModel.cpp
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * 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 "PreparedModel.h"
-
-#include <ExecutionBurstServer.h>
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.3/types.h>
-#include <hwbinder/IPCThreadState.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/TypeUtils.h>
-#include <nnapi/Types.h>
-#include <nnapi/Validation.h>
-#include <nnapi/hal/1.0/Utils.h>
-#include <nnapi/hal/1.2/Utils.h>
-#include <nnapi/hal/1.3/Conversions.h>
-#include <nnapi/hal/1.3/Utils.h>
-#include <nnapi/hal/HandleError.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <thread>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-namespace {
-
-template <typename Type>
-auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
- auto result = nn::convert(object);
- if (!result.has_value()) {
- result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
- }
- return result;
-}
-
-class FencedExecutionCallback final : public V1_3::IFencedExecutionCallback {
- public:
- explicit FencedExecutionCallback(const nn::ExecuteFencedInfoCallback& callback)
- : kCallback(callback) {
- CHECK(callback != nullptr);
- }
-
- Return<void> getExecutionInfo(getExecutionInfo_cb cb) override {
- const auto result = kCallback();
- if (!result.has_value()) {
- const auto& [message, code] = result.error();
- const auto status =
- V1_3::utils::convert(code).value_or(V1_3::ErrorStatus::GENERAL_FAILURE);
- LOG(ERROR) << message;
- cb(status, V1_2::utils::kNoTiming, V1_2::utils::kNoTiming);
- return Void();
- }
- const auto [timingLaunched, timingFenced] = result.value();
- const auto hidlTimingLaunched = V1_3::utils::convert(timingLaunched).value();
- const auto hidlTimingFenced = V1_3::utils::convert(timingFenced).value();
- cb(V1_3::ErrorStatus::NONE, hidlTimingLaunched, hidlTimingFenced);
- return Void();
- }
-
- private:
- const nn::ExecuteFencedInfoCallback kCallback;
-};
-
-using ExecutionResult = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
-
-void notify(V1_0::IExecutionCallback* callback, nn::ErrorStatus status,
- const std::vector<nn::OutputShape>& /*outputShapes*/, const nn::Timing& /*timing*/) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_0::utils::convert(status).value();
- const auto ret = callback->notify(hidlStatus);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_0::IExecutionCallback::notify failed with " << ret.description();
- }
- }
-}
-
-void notify(V1_2::IExecutionCallback* callback, nn::ErrorStatus status,
- const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_2::utils::convert(status).value();
- const auto hidlOutputShapes = V1_2::utils::convert(outputShapes).value();
- const auto hidlTiming = V1_2::utils::convert(timing).value();
- const auto ret = callback->notify_1_2(hidlStatus, hidlOutputShapes, hidlTiming);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_2::IExecutionCallback::notify_1_2 failed with " << ret.description();
- }
- }
-}
-
-void notify(V1_3::IExecutionCallback* callback, nn::ErrorStatus status,
- const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
- if (callback != nullptr) {
- const auto hidlStatus = V1_3::utils::convert(status).value();
- const auto hidlOutputShapes = V1_3::utils::convert(outputShapes).value();
- const auto hidlTiming = V1_3::utils::convert(timing).value();
- const auto ret = callback->notify_1_3(hidlStatus, hidlOutputShapes, hidlTiming);
- if (!ret.isOk()) {
- LOG(ERROR) << "V1_3::IExecutionCallback::notify_1_3 failed with " << ret.description();
- }
- }
-}
-
-template <typename CallbackType>
-void notify(CallbackType* callback, ExecutionResult result) {
- if (!result.has_value()) {
- const auto [message, status, outputShapes] = std::move(result).error();
- LOG(ERROR) << message;
- notify(callback, status, outputShapes, {});
- } else {
- const auto [outputShapes, timing] = std::move(result).value();
- notify(callback, nn::ErrorStatus::NONE, outputShapes, timing);
- }
-}
-
-nn::GeneralResult<void> execute(const nn::SharedPreparedModel& preparedModel, uid_t userId,
- const Executor& executor, const V1_0::Request& request,
- const sp<V1_0::IExecutionCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnRequest = NN_TRY(convertInput(request));
-
- const std::any resource = preparedModel->getUnderlyingResource();
- if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
- CHECK(*model != nullptr);
- NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
- nn::ErrorStatus::INVALID_ARGUMENT));
- }
-
- Task task = [preparedModel, nnRequest = std::move(nnRequest), callback] {
- auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {});
- notify(callback.get(), std::move(result));
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> execute_1_2(const nn::SharedPreparedModel& preparedModel, uid_t userId,
- const Executor& executor, const V1_0::Request& request,
- V1_2::MeasureTiming measure,
- const sp<V1_2::IExecutionCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnRequest = NN_TRY(convertInput(request));
- const auto nnMeasure = NN_TRY(convertInput(measure));
-
- const std::any resource = preparedModel->getUnderlyingResource();
- if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
- CHECK(*model != nullptr);
- NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
- nn::ErrorStatus::INVALID_ARGUMENT));
- }
-
- Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, callback] {
- auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {});
- notify(callback.get(), std::move(result));
- };
- executor(std::move(task), userId, {});
-
- return {};
-}
-
-nn::GeneralResult<void> execute_1_3(const nn::SharedPreparedModel& preparedModel, uid_t userId,
- const Executor& executor, const V1_3::Request& request,
- V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const sp<V1_3::IExecutionCallback>& callback) {
- if (callback.get() == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
- }
-
- auto nnRequest = NN_TRY(convertInput(request));
- const auto nnMeasure = NN_TRY(convertInput(measure));
- const auto nnDeadline = NN_TRY(convertInput(deadline));
- const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
-
- const std::any resource = preparedModel->getUnderlyingResource();
- if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
- CHECK(*model != nullptr);
- NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
- nn::ErrorStatus::INVALID_ARGUMENT));
- }
-
- Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, nnDeadline,
- nnLoopTimeoutDuration, callback] {
- auto result =
- preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration);
- notify(callback.get(), std::move(result));
- };
- executor(std::move(task), userId, nnDeadline);
-
- return {};
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously(
- const nn::SharedPreparedModel& preparedModel, const V1_0::Request& request,
- V1_2::MeasureTiming measure) {
- const auto nnRequest = NN_TRY(utils::makeExecutionFailure(convertInput(request)));
- const auto nnMeasure = NN_TRY(utils::makeExecutionFailure(convertInput(measure)));
-
- const auto [outputShapes, timing] =
- NN_TRY(preparedModel->execute(nnRequest, nnMeasure, {}, {}));
-
- auto hidlOutputShapes = NN_TRY(utils::makeExecutionFailure(V1_2::utils::convert(outputShapes)));
- const auto hidlTiming = NN_TRY(utils::makeExecutionFailure(V1_2::utils::convert(timing)));
- return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously_1_3(
- const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
- V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration) {
- const auto nnRequest = NN_TRY(utils::makeExecutionFailure(convertInput(request)));
- const auto nnMeasure = NN_TRY(utils::makeExecutionFailure(convertInput(measure)));
- const auto nnDeadline = NN_TRY(utils::makeExecutionFailure(convertInput(deadline)));
- const auto nnLoopTimeoutDuration =
- NN_TRY(utils::makeExecutionFailure(convertInput(loopTimeoutDuration)));
-
- const auto [outputShapes, timing] =
- NN_TRY(preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration));
-
- auto hidlOutputShapes = NN_TRY(utils::makeExecutionFailure(V1_3::utils::convert(outputShapes)));
- const auto hidlTiming = NN_TRY(utils::makeExecutionFailure(V1_3::utils::convert(timing)));
- return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
-}
-
-nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
- const hidl_vec<hidl_handle>& handles) {
- std::vector<nn::SyncFence> syncFences;
- syncFences.reserve(handles.size());
- for (const auto& handle : handles) {
- auto nativeHandle = NN_TRY(convertInput(handle));
- auto syncFence = NN_TRY(utils::makeGeneralFailure(
- nn::SyncFence::create(std::move(nativeHandle)), nn::ErrorStatus::INVALID_ARGUMENT));
- syncFences.push_back(std::move(syncFence));
- }
- return syncFences;
-}
-
-nn::GeneralResult<std::pair<hidl_handle, sp<V1_3::IFencedExecutionCallback>>> executeFenced(
- const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
- const hidl_vec<hidl_handle>& waitFor, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const V1_3::OptionalTimeoutDuration& duration) {
- const auto nnRequest = NN_TRY(convertInput(request));
- const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
- const auto nnMeasure = NN_TRY(convertInput(measure));
- const auto nnDeadline = NN_TRY(convertInput(deadline));
- const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
- const auto nnDuration = NN_TRY(convertInput(duration));
-
- auto [syncFence, executeFencedCallback] = NN_TRY(preparedModel->executeFenced(
- nnRequest, nnWaitFor, nnMeasure, nnDeadline, nnLoopTimeoutDuration, nnDuration));
-
- auto hidlSyncFence = NN_TRY(V1_3::utils::convert(syncFence.getSharedHandle()));
- auto hidlExecuteFencedCallback = sp<FencedExecutionCallback>::make(executeFencedCallback);
- return std::make_pair(std::move(hidlSyncFence), std::move(hidlExecuteFencedCallback));
-}
-
-} // namespace
-
-PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel, Executor executor, uid_t userId)
- : kPreparedModel(std::move(preparedModel)), kExecutor(std::move(executor)), kUserId(userId) {
- CHECK(kPreparedModel != nullptr);
- CHECK(kExecutor != nullptr);
-}
-
-nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
- return kPreparedModel;
-}
-
-Return<V1_0::ErrorStatus> PreparedModel::execute(const V1_0::Request& request,
- const sp<V1_0::IExecutionCallback>& callback) {
- auto result = adapter::execute(kPreparedModel, kUserId, kExecutor, request, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::execute failed with " << code << ": " << message;
- notify(callback.get(), code, {}, {});
- return V1_0::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> PreparedModel::execute_1_2(const V1_0::Request& request,
- V1_2::MeasureTiming measure,
- const sp<V1_2::IExecutionCallback>& callback) {
- auto result =
- adapter::execute_1_2(kPreparedModel, kUserId, kExecutor, request, measure, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::execute_1_2 failed with " << code << ": " << message;
- notify(callback.get(), code, {}, {});
- return V1_2::utils::convert(code).value();
- }
- return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_3::ErrorStatus> PreparedModel::execute_1_3(
- const V1_3::Request& request, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const sp<V1_3::IExecutionCallback>& callback) {
- auto result = adapter::execute_1_3(kPreparedModel, kUserId, kExecutor, request, measure,
- deadline, loopTimeoutDuration, callback);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::execute_1_3 failed with " << code << ": " << message;
- notify(callback.get(), code, {}, {});
- return V1_3::utils::convert(code).value();
- }
- return V1_3::ErrorStatus::NONE;
-}
-
-Return<void> PreparedModel::executeSynchronously(const V1_0::Request& request,
- V1_2::MeasureTiming measure,
- executeSynchronously_cb cb) {
- auto result = adapter::executeSynchronously(kPreparedModel, request, measure);
- if (!result.has_value()) {
- auto [message, code, outputShapes] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::executeSynchronously failed with " << code << ": "
- << message;
- cb(V1_2::utils::convert(code).value(), V1_2::utils::convert(outputShapes).value(),
- V1_2::utils::kNoTiming);
- return Void();
- }
- auto [outputShapes, timing] = std::move(result).value();
- cb(V1_0::ErrorStatus::NONE, outputShapes, timing);
- return Void();
-}
-
-Return<void> PreparedModel::executeSynchronously_1_3(
- const V1_3::Request& request, V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration, executeSynchronously_1_3_cb cb) {
- auto result = adapter::executeSynchronously_1_3(kPreparedModel, request, measure, deadline,
- loopTimeoutDuration);
- if (!result.has_value()) {
- auto [message, code, outputShapes] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::executeSynchronously_1_3 failed with " << code
- << ": " << message;
- cb(V1_3::utils::convert(code).value(), V1_3::utils::convert(outputShapes).value(),
- V1_2::utils::kNoTiming);
- return Void();
- }
- auto [outputShapes, timing] = std::move(result).value();
- cb(V1_3::ErrorStatus::NONE, outputShapes, timing);
- return Void();
-}
-
-Return<void> PreparedModel::configureExecutionBurst(
- const sp<V1_2::IBurstCallback>& callback,
- const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
- const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
- configureExecutionBurst_cb cb) {
- const sp<V1_2::IBurstContext> burst = nn::ExecutionBurstServer::create(
- callback, requestChannel, resultChannel, this, std::chrono::microseconds{0});
-
- if (burst == nullptr) {
- cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
- } else {
- cb(V1_0::ErrorStatus::NONE, burst);
- }
- return Void();
-}
-
-Return<void> PreparedModel::executeFenced(const V1_3::Request& request,
- const hidl_vec<hidl_handle>& waitFor,
- V1_2::MeasureTiming measure,
- const V1_3::OptionalTimePoint& deadline,
- const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
- const V1_3::OptionalTimeoutDuration& duration,
- executeFenced_cb callback) {
- auto result = adapter::executeFenced(kPreparedModel, request, waitFor, measure, deadline,
- loopTimeoutDuration, duration);
- if (!result.has_value()) {
- auto [message, code] = std::move(result).error();
- LOG(ERROR) << "adapter::PreparedModel::executeFenced failed with " << code << ": "
- << message;
- callback(V1_3::utils::convert(code).value(), {}, nullptr);
- return Void();
- }
- auto [syncFence, executeFencedCallback] = std::move(result).value();
- callback(V1_3::ErrorStatus::NONE, syncFence, executeFencedCallback);
- return Void();
-}
-
-} // namespace android::hardware::neuralnetworks::adapter