Add QoS types to NNAPI runtime
Bug: 136739795
Bug: 142902514
Bug: 145300530
Test: mma
Change-Id: If3ce646d512b02daa78479aa7c75de99e20def21
diff --git a/nn/common/ExecutionBurstController.cpp b/nn/common/ExecutionBurstController.cpp
index 1136024..eb956de 100644
--- a/nn/common/ExecutionBurstController.cpp
+++ b/nn/common/ExecutionBurstController.cpp
@@ -144,7 +144,7 @@
}
// deserialize a packet into the result
-std::optional<std::tuple<ErrorStatus, std::vector<OutputShape>, Timing>> deserialize(
+std::optional<std::tuple<V1_0::ErrorStatus, std::vector<OutputShape>, Timing>> deserialize(
const std::vector<FmqResultDatum>& data) {
using discriminator = FmqResultDatum::hidl_discriminator;
@@ -161,7 +161,7 @@
const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation();
index++;
const uint32_t packetSize = packetInfo.packetSize;
- const ErrorStatus errorStatus = packetInfo.errorStatus;
+ const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus;
const uint32_t numberOfOperands = packetInfo.numberOfOperands;
// verify packet size
@@ -245,7 +245,7 @@
std::chrono::microseconds pollingTimeWindow)
: mFmqResultChannel(std::move(fmqResultChannel)), kPollingTimeWindow(pollingTimeWindow) {}
-std::optional<std::tuple<ErrorStatus, std::vector<OutputShape>, Timing>>
+std::optional<std::tuple<V1_0::ErrorStatus, std::vector<OutputShape>, Timing>>
ResultChannelReceiver::getBlocking() {
const auto packet = getPacketBlocking();
if (!packet) {
@@ -266,7 +266,7 @@
// TODO: look for a different/better way to signal/notify the futex to
// wake up any thread waiting on it
FmqResultDatum datum;
- datum.packetInformation({/*.packetSize=*/0, /*.errorStatus=*/ErrorStatus::GENERAL_FAILURE,
+ datum.packetInformation({/*.packetSize=*/0, /*.errorStatus=*/V1_0::ErrorStatus::GENERAL_FAILURE,
/*.numberOfOperands=*/0});
mFmqResultChannel->writeBlocking(&datum, 1);
}
@@ -395,12 +395,12 @@
// ensure all memories are valid
if (!std::all_of(memories.begin(), memories.end(),
[](const hidl_memory& memory) { return memory.valid(); })) {
- cb(ErrorStatus::INVALID_ARGUMENT, {});
+ cb(V1_0::ErrorStatus::INVALID_ARGUMENT, {});
return Void();
}
// return successful
- cb(ErrorStatus::NONE, std::move(memories));
+ cb(V1_0::ErrorStatus::NONE, std::move(memories));
return Void();
}
@@ -494,11 +494,12 @@
}
// configure burst
- ErrorStatus errorStatus;
+ V1_0::ErrorStatus errorStatus;
sp<IBurstContext> burstContext;
const Return<void> ret = preparedModel->configureExecutionBurst(
callback, *requestChannelDescriptor, *resultChannelDescriptor,
- [&errorStatus, &burstContext](ErrorStatus status, const sp<IBurstContext>& context) {
+ [&errorStatus, &burstContext](V1_0::ErrorStatus status,
+ const sp<IBurstContext>& context) {
errorStatus = status;
burstContext = context;
});
@@ -509,7 +510,7 @@
<< ret.description();
return nullptr;
}
- if (errorStatus != ErrorStatus::NONE) {
+ if (errorStatus != V1_0::ErrorStatus::NONE) {
LOG(ERROR) << "IPreparedModel::configureExecutionBurst failed with status "
<< toString(errorStatus);
return nullptr;
@@ -565,9 +566,10 @@
}
static std::tuple<int, std::vector<OutputShape>, Timing, bool> getExecutionResult(
- ErrorStatus status, std::vector<OutputShape> outputShapes, Timing timing, bool fallback) {
+ V1_0::ErrorStatus status, std::vector<OutputShape> outputShapes, Timing timing,
+ bool fallback) {
auto [n, checkedOutputShapes, checkedTiming] =
- getExecutionResult(status, std::move(outputShapes), timing);
+ getExecutionResult(convertToV1_3(status), std::move(outputShapes), timing);
return {n, std::move(checkedOutputShapes), checkedTiming, fallback};
}
@@ -589,7 +591,8 @@
if (!success) {
LOG(ERROR) << "Error sending FMQ packet";
// only use fallback execution path if the packet could not be sent
- return getExecutionResult(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming, /*fallback=*/true);
+ return getExecutionResult(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming,
+ /*fallback=*/true);
}
// get result packet
@@ -597,7 +600,8 @@
if (!result) {
LOG(ERROR) << "Error retrieving FMQ packet";
// only use fallback execution path if the packet could not be sent
- return getExecutionResult(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming, /*fallback=*/false);
+ return getExecutionResult(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming,
+ /*fallback=*/false);
}
// unpack results and return (only use fallback execution path if the
diff --git a/nn/common/ExecutionBurstServer.cpp b/nn/common/ExecutionBurstServer.cpp
index 890b653..7cd130f 100644
--- a/nn/common/ExecutionBurstServer.cpp
+++ b/nn/common/ExecutionBurstServer.cpp
@@ -62,7 +62,7 @@
void removeCacheEntry(int32_t slot) override { mMemoryCache.erase(slot); }
- std::tuple<ErrorStatus, hidl_vec<OutputShape>, Timing> execute(
+ std::tuple<V1_0::ErrorStatus, hidl_vec<OutputShape>, Timing> execute(
const V1_0::Request& request, const std::vector<int32_t>& slots,
MeasureTiming measure) override {
// convert slots to pools
@@ -75,11 +75,11 @@
fullRequest.pools = std::move(pools);
// setup execution
- ErrorStatus returnedStatus = ErrorStatus::GENERAL_FAILURE;
+ V1_0::ErrorStatus returnedStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
hidl_vec<OutputShape> returnedOutputShapes;
Timing returnedTiming;
auto cb = [&returnedStatus, &returnedOutputShapes, &returnedTiming](
- ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
+ V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
const Timing& timing) {
returnedStatus = status;
returnedOutputShapes = outputShapes;
@@ -88,7 +88,7 @@
// execute
const Return<void> ret = mpPreparedModel->executeSynchronously(fullRequest, measure, cb);
- if (!ret.isOk() || returnedStatus != ErrorStatus::NONE) {
+ if (!ret.isOk() || returnedStatus != V1_0::ErrorStatus::NONE) {
LOG(ERROR) << "IPreparedModelAdapter::execute -- Error executing";
return {returnedStatus, {}, kNoTiming};
}
@@ -104,7 +104,7 @@
} // anonymous namespace
// serialize result
-std::vector<FmqResultDatum> serialize(ErrorStatus errorStatus,
+std::vector<FmqResultDatum> serialize(V1_0::ErrorStatus errorStatus,
const std::vector<OutputShape>& outputShapes, Timing timing) {
// count how many elements need to be sent for a request
size_t count = 2 + outputShapes.size();
@@ -458,7 +458,7 @@
ResultChannelSender::ResultChannelSender(std::unique_ptr<FmqResultChannel> fmqResultChannel)
: mFmqResultChannel(std::move(fmqResultChannel)) {}
-bool ResultChannelSender::send(ErrorStatus errorStatus,
+bool ResultChannelSender::send(V1_0::ErrorStatus errorStatus,
const std::vector<OutputShape>& outputShapes, Timing timing) {
const std::vector<FmqResultDatum> serialized = serialize(errorStatus, outputShapes, timing);
return sendPacket(serialized);
@@ -469,7 +469,7 @@
LOG(ERROR)
<< "ResultChannelSender::sendPacket -- packet size exceeds size available in FMQ";
const std::vector<FmqResultDatum> errorPacket =
- serialize(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+ serialize(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
// Always send the packet with "blocking" because this signals the futex
// and unblocks the consumer if it is waiting on the futex.
@@ -575,9 +575,9 @@
return;
}
- ErrorStatus errorStatus = ErrorStatus::GENERAL_FAILURE;
+ V1_0::ErrorStatus errorStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
std::vector<hidl_memory> returnedMemories;
- auto cb = [&errorStatus, &returnedMemories](ErrorStatus status,
+ auto cb = [&errorStatus, &returnedMemories](V1_0::ErrorStatus status,
const hidl_vec<hidl_memory>& memories) {
errorStatus = status;
returnedMemories = memories;
@@ -585,7 +585,7 @@
const Return<void> ret = mCallback->getMemories(unknownSlots, cb);
- if (!ret.isOk() || errorStatus != ErrorStatus::NONE ||
+ if (!ret.isOk() || errorStatus != V1_0::ErrorStatus::NONE ||
returnedMemories.size() != unknownSlots.size()) {
LOG(ERROR) << "Error retrieving memories";
return;
@@ -610,7 +610,7 @@
// "task" function can end
if (!arguments) {
if (!mTeardown) {
- mResultChannelSender->send(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+ mResultChannelSender->send(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
}
continue;
}
diff --git a/nn/common/Utils.cpp b/nn/common/Utils.cpp
index 195b804..f753a16 100644
--- a/nn/common/Utils.cpp
+++ b/nn/common/Utils.cpp
@@ -1658,40 +1658,51 @@
case ANEURALNETWORKS_UNAVAILABLE_DEVICE:
return ErrorStatus::DEVICE_UNAVAILABLE;
- default:
- LOG(ERROR) << "Unknown result code " << resultCode
- << " mapped to ErrorStatus::GENERAL_FAILURE";
- return ErrorStatus::GENERAL_FAILURE;
case ANEURALNETWORKS_BAD_STATE:
case ANEURALNETWORKS_INCOMPLETE:
case ANEURALNETWORKS_OP_FAILED:
case ANEURALNETWORKS_OUT_OF_MEMORY:
case ANEURALNETWORKS_UNMAPPABLE:
+ case ANEURALNETWORKS_DEAD_OBJECT:
return ErrorStatus::GENERAL_FAILURE;
+
+ case ANEURALNETWORKS_MISSED_DEADLINE_TRANSIENT:
+ return ErrorStatus::MISSED_DEADLINE_TRANSIENT;
+ case ANEURALNETWORKS_MISSED_DEADLINE_PERSISTENT:
+ return ErrorStatus::MISSED_DEADLINE_PERSISTENT;
+ case ANEURALNETWORKS_RESOURCE_EXHAUSTED_TRANSIENT:
+ return ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT;
+ case ANEURALNETWORKS_RESOURCE_EXHAUSTED_PERSISTENT:
+ return ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT;
}
+ LOG(ERROR) << "Unknown result code " << resultCode << " mapped to ErrorStatus::GENERAL_FAILURE";
+ return ErrorStatus::GENERAL_FAILURE;
}
int convertErrorStatusToResultCode(ErrorStatus status) {
switch (status) {
case ErrorStatus::NONE:
return ANEURALNETWORKS_NO_ERROR;
-
- case ErrorStatus::INVALID_ARGUMENT:
- return ANEURALNETWORKS_BAD_DATA;
-
- case ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
- return ANEURALNETWORKS_OUTPUT_INSUFFICIENT_SIZE;
-
case ErrorStatus::DEVICE_UNAVAILABLE:
return ANEURALNETWORKS_UNAVAILABLE_DEVICE;
-
- default:
- LOG(ERROR) << "Unknown ErrorStatus " << toString(status)
- << " mapped to ANEURALNETWORKS_OP_FAILED";
- return ANEURALNETWORKS_OP_FAILED;
case ErrorStatus::GENERAL_FAILURE:
return ANEURALNETWORKS_OP_FAILED;
+ case ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+ return ANEURALNETWORKS_OUTPUT_INSUFFICIENT_SIZE;
+ case ErrorStatus::INVALID_ARGUMENT:
+ return ANEURALNETWORKS_BAD_DATA;
+ case ErrorStatus::MISSED_DEADLINE_TRANSIENT:
+ return ANEURALNETWORKS_MISSED_DEADLINE_TRANSIENT;
+ case ErrorStatus::MISSED_DEADLINE_PERSISTENT:
+ return ANEURALNETWORKS_MISSED_DEADLINE_PERSISTENT;
+ case ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
+ return ANEURALNETWORKS_RESOURCE_EXHAUSTED_TRANSIENT;
+ case ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
+ return ANEURALNETWORKS_RESOURCE_EXHAUSTED_PERSISTENT;
}
+ LOG(ERROR) << "Unknown ErrorStatus " << toString(status)
+ << " mapped to ANEURALNETWORKS_OP_FAILED";
+ return ANEURALNETWORKS_OP_FAILED;
}
std::tuple<int, std::vector<OutputShape>, Timing> getExecutionResult(
@@ -1950,6 +1961,43 @@
return true;
}
+V1_0::ErrorStatus convertToV1_0(V1_0::ErrorStatus status) {
+ return status;
+}
+
+V1_0::ErrorStatus convertToV1_0(V1_3::ErrorStatus status) {
+ switch (status) {
+ case V1_3::ErrorStatus::NONE:
+ return V1_0::ErrorStatus::NONE;
+ case V1_3::ErrorStatus::DEVICE_UNAVAILABLE:
+ return V1_0::ErrorStatus::DEVICE_UNAVAILABLE;
+ case V1_3::ErrorStatus::GENERAL_FAILURE:
+ return V1_0::ErrorStatus::GENERAL_FAILURE;
+ case V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
+ return V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+ case V1_3::ErrorStatus::INVALID_ARGUMENT:
+ return V1_0::ErrorStatus::INVALID_ARGUMENT;
+ case V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
+ return V1_0::ErrorStatus::GENERAL_FAILURE;
+ case V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
+ return V1_0::ErrorStatus::GENERAL_FAILURE;
+ case V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
+ return V1_0::ErrorStatus::GENERAL_FAILURE;
+ case V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
+ return V1_0::ErrorStatus::GENERAL_FAILURE;
+ }
+ LOG(ERROR) << "Unknown ErrorStatus: " << toString(status) << " mapped to GENERAL_FAILURE";
+ return V1_0::ErrorStatus::GENERAL_FAILURE;
+}
+
+V1_3::ErrorStatus convertToV1_3(V1_0::ErrorStatus status) {
+ return static_cast<V1_3::ErrorStatus>(status);
+}
+
+V1_3::ErrorStatus convertToV1_3(V1_3::ErrorStatus status) {
+ return status;
+}
+
static V1_0::OperationType uncheckedConvertToV1_0(V1_1::OperationType type) {
return static_cast<V1_0::OperationType>(type);
}
diff --git a/nn/common/include/ExecutionBurstController.h b/nn/common/include/ExecutionBurstController.h
index 15db0fc..e8f3657 100644
--- a/nn/common/include/ExecutionBurstController.h
+++ b/nn/common/include/ExecutionBurstController.h
@@ -64,8 +64,8 @@
* @param data Serialized FMQ result data.
* @return Result object if successfully deserialized, std::nullopt otherwise.
*/
-std::optional<std::tuple<hal::ErrorStatus, std::vector<hal::OutputShape>, hal::Timing>> deserialize(
- const std::vector<hal::FmqResultDatum>& data);
+std::optional<std::tuple<hal::V1_0::ErrorStatus, std::vector<hal::OutputShape>, hal::Timing>>
+deserialize(const std::vector<hal::FmqResultDatum>& data);
/**
* ResultChannelReceiver is responsible for waiting on the channel until the
@@ -108,7 +108,7 @@
* @return Result object if successfully received, std::nullopt if error or
* if the receiver object was invalidated.
*/
- std::optional<std::tuple<hal::ErrorStatus, std::vector<hal::OutputShape>, hal::Timing>>
+ std::optional<std::tuple<hal::V1_0::ErrorStatus, std::vector<hal::OutputShape>, hal::Timing>>
getBlocking();
/**
diff --git a/nn/common/include/ExecutionBurstServer.h b/nn/common/include/ExecutionBurstServer.h
index 5bac095..2a0dfba 100644
--- a/nn/common/include/ExecutionBurstServer.h
+++ b/nn/common/include/ExecutionBurstServer.h
@@ -46,7 +46,7 @@
* @param timing Timing information of the execution.
* @return Serialized FMQ result data.
*/
-std::vector<hal::FmqResultDatum> serialize(hal::ErrorStatus errorStatus,
+std::vector<hal::FmqResultDatum> serialize(hal::V1_0::ErrorStatus errorStatus,
const std::vector<hal::OutputShape>& outputShapes,
hal::Timing timing);
@@ -151,7 +151,7 @@
* @param timing Timing information of the execution.
* @return 'true' on successful send, 'false' otherwise.
*/
- bool send(hal::ErrorStatus errorStatus, const std::vector<hal::OutputShape>& outputShapes,
+ bool send(hal::V1_0::ErrorStatus errorStatus, const std::vector<hal::OutputShape>& outputShapes,
hal::Timing timing);
// prefer calling ResultChannelSender::send
@@ -233,8 +233,8 @@
* @return Result of the execution, including the status of the
* execution, dynamic output shapes, and any timing information.
*/
- virtual std::tuple<hal::ErrorStatus, hal::hidl_vec<hal::OutputShape>, hal::Timing> execute(
- const hal::V1_0::Request& request, const std::vector<int32_t>& slots,
+ virtual std::tuple<hal::V1_0::ErrorStatus, hal::hidl_vec<hal::OutputShape>, hal::Timing>
+ execute(const hal::V1_0::Request& request, const std::vector<int32_t>& slots,
hal::MeasureTiming measure) = 0;
};
diff --git a/nn/common/include/HalInterfaces.h b/nn/common/include/HalInterfaces.h
index 8efbf21..fc18e2b 100644
--- a/nn/common/include/HalInterfaces.h
+++ b/nn/common/include/HalInterfaces.h
@@ -30,6 +30,7 @@
#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
#include <android/hardware/neuralnetworks/1.2/types.h>
#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
#include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
#include <android/hardware/neuralnetworks/1.3/types.h>
@@ -60,7 +61,6 @@
using V1_0::DataLocation;
using V1_0::DeviceStatus;
-using V1_0::ErrorStatus;
using V1_0::FusedActivationFunc;
using V1_0::PerformanceInfo;
using V1_0::RequestArgument;
@@ -72,7 +72,6 @@
using V1_2::FmqResultDatum;
using V1_2::IBurstCallback;
using V1_2::IBurstContext;
-using V1_2::IExecutionCallback;
using V1_2::MeasureTiming;
using V1_2::OutputShape;
using V1_2::SymmPerChannelQuantParams;
@@ -80,8 +79,10 @@
using V1_3::BufferDesc;
using V1_3::BufferRole;
using V1_3::Capabilities;
+using V1_3::ErrorStatus;
using V1_3::IBuffer;
using V1_3::IDevice;
+using V1_3::IExecutionCallback;
using V1_3::IPreparedModel;
using V1_3::IPreparedModelCallback;
using V1_3::Model;
@@ -92,6 +93,8 @@
using V1_3::Operation;
using V1_3::OperationType;
using V1_3::OperationTypeRange;
+using V1_3::OptionalTimePoint;
+using V1_3::Priority;
using V1_3::Request;
using V1_3::Subgraph;
using ExtensionNameAndPrefix = V1_2::Model::ExtensionNameAndPrefix;
@@ -101,6 +104,8 @@
hardware::hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
using ModelFactory = std::function<Model()>;
+inline constexpr Priority kDefaultPriority = Priority::MEDIUM;
+
} // namespace android::nn::hal
#endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_HAL_INTERFACES_H
diff --git a/nn/common/include/Utils.h b/nn/common/include/Utils.h
index ada19fc..2d341ef 100644
--- a/nn/common/include/Utils.h
+++ b/nn/common/include/Utils.h
@@ -22,6 +22,7 @@
#include <set>
#include <string>
#include <tuple>
+#include <utility>
#include <vector>
#include "HalInterfaces.h"
@@ -385,6 +386,11 @@
bool compliantWithV1_2(const hal::V1_3::Model& model,
std::set<uint32_t>* noncompliantOperations = nullptr);
+hal::V1_0::ErrorStatus convertToV1_0(hal::V1_0::ErrorStatus status);
+hal::V1_0::ErrorStatus convertToV1_0(hal::V1_3::ErrorStatus status);
+hal::V1_3::ErrorStatus convertToV1_3(hal::V1_0::ErrorStatus status);
+hal::V1_3::ErrorStatus convertToV1_3(hal::V1_3::ErrorStatus status);
+
hal::V1_0::Capabilities convertToV1_0(const hal::V1_0::Capabilities& capabilities);
hal::V1_0::Capabilities convertToV1_0(const hal::V1_1::Capabilities& capabilities);
hal::V1_0::Capabilities convertToV1_0(const hal::V1_2::Capabilities& capabilities);
@@ -459,6 +465,19 @@
hal::V1_3::OperandLifeTime convertToV1_3(hal::V1_0::OperandLifeTime lifetime);
hal::V1_3::OperandLifeTime convertToV1_3(hal::V1_3::OperandLifeTime lifetime);
+constexpr hal::Priority convertToHalPriority(int32_t priority) {
+ switch (priority) {
+ case ANEURALNETWORKS_PRIORITY_LOW:
+ return hal::Priority::LOW;
+ case ANEURALNETWORKS_PRIORITY_MEDIUM:
+ return hal::Priority::MEDIUM;
+ case ANEURALNETWORKS_PRIORITY_HIGH:
+ return hal::Priority::HIGH;
+ }
+ LOG(FATAL) << "unrecognized priority: " << priority;
+ return {};
+}
+
#ifdef NN_DEBUGGABLE
uint32_t getProp(const char* str, uint32_t defaultValue = 0);
#endif // NN_DEBUGGABLE