Add TENSOR_QUANT8_ASYMM_SIGNED support for TOPK_V2 op

Bug: 143935115
Test: quantization coupling tests in CTS and VTS
Change-Id: Ibf028b3dba23d0ff381639c5f2830c154b1566d2
diff --git a/nn/common/Utils.cpp b/nn/common/Utils.cpp
index 169845a..706c01e 100644
--- a/nn/common/Utils.cpp
+++ b/nn/common/Utils.cpp
@@ -1741,7 +1741,8 @@
             if (inputType == OperandType::TENSOR_FLOAT16 ||
                 inputType == OperandType::TENSOR_FLOAT32 ||
                 inputType == OperandType::TENSOR_INT32 ||
-                inputType == OperandType::TENSOR_QUANT8_ASYMM) {
+                inputType == OperandType::TENSOR_QUANT8_ASYMM ||
+                inputType == OperandType::TENSOR_QUANT8_ASYMM_SIGNED) {
                 inExpectedTypes = {inputType, OperandType::INT32};
                 outExpectedTypes = {inputType, OperandType::TENSOR_INT32};
             } else {
@@ -1749,7 +1750,11 @@
                            << getOperationName(opType);
                 return ANEURALNETWORKS_BAD_DATA;
             }
-            NN_RETURN_IF_ERROR(validateHalVersion(opType, halVersion, HalVersion::V1_2));
+            if (inputType == OperandType::TENSOR_QUANT8_ASYMM_SIGNED) {
+                NN_RETURN_IF_ERROR(validateHalVersion(opType, halVersion, HalVersion::V1_3));
+            } else {
+                NN_RETURN_IF_ERROR(validateHalVersion(opType, halVersion, HalVersion::V1_2));
+            }
             return validateOperationOperandTypes(operands, inputCount, inputIndexes,
                                                  inExpectedTypes, outputCount, outputIndexes,
                                                  outExpectedTypes);
diff --git a/nn/common/operations/TopK_V2.cpp b/nn/common/operations/TopK_V2.cpp
index 010d380..00c88a1 100644
--- a/nn/common/operations/TopK_V2.cpp
+++ b/nn/common/operations/TopK_V2.cpp
@@ -22,6 +22,8 @@
 #include "OperationsUtils.h"
 
 #include <algorithm>
+#include <utility>
+#include <vector>
 
 namespace android {
 namespace nn {
@@ -93,6 +95,11 @@
                                reinterpret_cast<uint8_t*>(valuesData), valuesShape,
                                reinterpret_cast<int32_t*>(indicesData), indicesShape);
         } break;
+        case OperandType::TENSOR_QUANT8_ASYMM_SIGNED: {
+            return evalGeneric(reinterpret_cast<const int8_t*>(inputData), inputShape, k,
+                               reinterpret_cast<int8_t*>(valuesData), valuesShape,
+                               reinterpret_cast<int32_t*>(indicesData), indicesShape);
+        } break;
         default: {
             LOG(ERROR) << "Unsupported data type: " << toString(inputShape.type);
             return false;
diff --git a/nn/runtime/include/NeuralNetworks.h b/nn/runtime/include/NeuralNetworks.h
index 7c2c301..df384ae 100644
--- a/nn/runtime/include/NeuralNetworks.h
+++ b/nn/runtime/include/NeuralNetworks.h
@@ -4568,6 +4568,7 @@
      * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
      * * {@link ANEURALNETWORKS_TENSOR_INT32}
      * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
+     * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED} (since API level 30)
      *
      * Supported tensor rank: from 1
      *
@@ -4579,7 +4580,8 @@
      * Outputs:
      * * 0: An n-D tensor of the same type as the input, containing the k
      *      largest elements along each last dimensional slice.
-     *      For a {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} and
+     *      {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      * * 1: An n-D tensor of type {@link ANEURALNETWORKS_TENSOR_INT32}
      *      containing the indices of values within the last dimension of input.
diff --git a/nn/runtime/test/TestValidateOperations.cpp b/nn/runtime/test/TestValidateOperations.cpp
index 8a61663..d30e0e5 100644
--- a/nn/runtime/test/TestValidateOperations.cpp
+++ b/nn/runtime/test/TestValidateOperations.cpp
@@ -592,6 +592,7 @@
     topkV2Test(ANEURALNETWORKS_TENSOR_FLOAT32);
     topkV2Test(ANEURALNETWORKS_TENSOR_INT32);
     topkV2Test(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
+    topkV2Test(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
 }
 
 void simpleMathOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
diff --git a/nn/tools/api/types.spec b/nn/tools/api/types.spec
index f3011b3..3b8a563 100644
--- a/nn/tools/api/types.spec
+++ b/nn/tools/api/types.spec
@@ -4934,6 +4934,9 @@
      * * {@link %{OperandTypeLinkPfx}TENSOR_FLOAT32}
      * * {@link %{OperandTypeLinkPfx}TENSOR_INT32}
      * * {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM}
+%kind ndk hal_1.3+
+     * * {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM_SIGNED} (since %{APILevel30})
+%/kind
      *
      * Supported tensor rank: from 1
      *
@@ -4945,8 +4948,14 @@
      * Outputs:
      * * 0: An n-D tensor of the same type as the input, containing the k
      *      largest elements along each last dimensional slice.
+%kind ndk hal_1.3+
+     *      For a {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM} and
+     *      {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM_SIGNED} tensor,
+     *      the scale and zeroPoint must be the same as input0.
+%else
      *      For a {@link %{OperandTypeLinkPfx}TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
+%/kind
      * * 1: An n-D tensor of type {@link %{OperandTypeLinkPfx}TENSOR_INT32}
      *      containing the indices of values within the last dimension of input.
 %insert-lines AVAIL29