Add 1.2 NN HAL interface for dynamic output shape.
Let notify_1_2() notify output shapes.
Document unspecified dimensions and rank.
Bug: 73506513
Bug: 77234888
Test: NeuralNetworksTest_static
Test: VtsHalNeuralnetworksV1_xTargetTest with 1.2 sample driver
Change-Id: I01108913212d9f4aa47daf2f293ea19259925865
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 7d13104..d8762b0 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -27,6 +27,7 @@
"Operation",
"OperationType",
"OperationTypeRange",
+ "OutputShape",
],
gen_java: false,
}
diff --git a/neuralnetworks/1.2/IExecutionCallback.hal b/neuralnetworks/1.2/IExecutionCallback.hal
index 667e0d6..47de1b6 100644
--- a/neuralnetworks/1.2/IExecutionCallback.hal
+++ b/neuralnetworks/1.2/IExecutionCallback.hal
@@ -18,6 +18,7 @@
import @1.0::ErrorStatus;
import @1.0::IExecutionCallback;
+import OutputShape;
/**
* IExecutionCallback must be used to return the error status result from an
@@ -39,10 +40,16 @@
* - DEVICE_UNAVAILABLE if driver is offline or busy
* - GENERAL_FAILURE if the asynchronous task resulted in an
* unspecified error
- * - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
- * not large enough to store the resultant values
+ * - 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 with to index
+ * of the output operand in the Request outputs vector.
+ * outputShapes must be empty unless the status is either
+ * NONE or OUTPUT_INSUFFICIENT_SIZE.
*/
- oneway notify_1_2(ErrorStatus status);
+ oneway notify_1_2(ErrorStatus status, vec<OutputShape> outputShapes);
};
diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal
index 4e91c67..044ca28 100644
--- a/neuralnetworks/1.2/IPreparedModel.hal
+++ b/neuralnetworks/1.2/IPreparedModel.hal
@@ -100,11 +100,17 @@
* - NONE if execution is performed successfully
* - 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
+ * - 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 is
* invalid
+ * @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.
*/
executeSynchronously(Request request)
- generates (ErrorStatus status);
+ generates (ErrorStatus status, vec<OutputShape> outputShapes);
};
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 40c07e7..4738cc3 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -234,9 +234,6 @@
*
* For a scalar operand, dimensions.size() must be 0.
*
- * For a tensor operand, dimensions.size() must be at least 1;
- * however, any of the dimensions may be unspecified.
- *
* A tensor operand with all dimensions specified has "fully
* specified" dimensions. Whenever possible (i.e., whenever the
* dimensions are known at model construction time), a tensor
@@ -255,17 +252,20 @@
* . The operand has lifetime CONSTANT_COPY or
* CONSTANT_REFERENCE.
*
- * . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
+ * . The operand has lifetime MODEL_INPUT. Fully
* specified dimensions must either be present in the
* Operand or they must be provided in the corresponding
* RequestArgument.
- * EXCEPTION: If the input or output is optional and omitted
+ * EXCEPTION: If the input is optional and omitted
* (by setting the hasNoValue field of the corresponding
* RequestArgument to true) then it need not have fully
* specified dimensions.
*
* A tensor operand with some number of unspecified dimensions is
* represented by setting each unspecified dimension to 0.
+ *
+ * A tensor operand with unspecified rank is represented by providing
+ * an empty dimensions vector.
*/
vec<uint32_t> dimensions;
@@ -397,3 +397,18 @@
*/
bool relaxComputationFloat32toFloat16;
};
+
+/**
+ * Describes the shape information of an output operand after execution.
+ */
+struct OutputShape {
+ /**
+ * Dimensions of the operand.
+ */
+ vec<uint32_t> dimensions;
+
+ /**
+ * Whether the provided buffer size is sufficient for the output.
+ */
+ bool isSufficient;
+};
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index d80fbcf..1eaea4b 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -110,15 +110,20 @@
executionCallback->wait();
ErrorStatus executionReturnStatus = executionCallback->getStatus();
+ const auto& outputShapes = executionCallback->getOutputShapes();
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+ ASSERT_EQ(outputShapes.size(), 0);
}
{
SCOPED_TRACE(message + " [executeSynchronously]");
- Return<ErrorStatus> executeStatus = preparedModel->executeSynchronously(request);
+ Return<void> executeStatus = preparedModel->executeSynchronously(
+ request, [](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes) {
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+ EXPECT_EQ(outputShapes.size(), 0);
+ });
ASSERT_TRUE(executeStatus.isOk());
- ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeStatus));
}
}