Validate FULLY_CONNECTED outputScale > inputScale * weightsScale below v1.2 FULLY_CONNECTED's constraint "outputScale > inputScale * weightsScale" was relaxed for HAL v1.2, but the appropriate version checks were not put in place. For more information about this check, refer to the description of the output operand for FULLY_CONNECTED in NeuralNetworks.h. Bug: 130169097 Test: NeuralNetworkTest_static Change-Id: Id8baa985efbf2978f88b7cfc732ae6d0c68a5a33 Merged-In: Id8baa985efbf2978f88b7cfc732ae6d0c68a5a33 (cherry picked from commit 0a0f75e852a87d2cb99ea590a08e6a34dcd31802)
diff --git a/common/operations/FullyConnected.cpp b/common/operations/FullyConnected.cpp index 14cd431..542fb53 100644 --- a/common/operations/FullyConnected.cpp +++ b/common/operations/FullyConnected.cpp
@@ -161,7 +161,20 @@ OperandType::INT32, }; } else if (inputType == OperandType::TENSOR_QUANT8_ASYMM) { - NN_RET_CHECK(validateHalVersion(context, HalVersion::V1_0)); + // NeuralNetworks.h specifies that ANEURALNETWORKS_FULLY_CONNECTED's output must + // meet "outputScale > inputScale * weightsScale" for the operand type + // ANEURALNETWORKS_TENSOR_QUANT8_ASYMM before API level 29. + const float inputScale = context->getInputShape(kInputTensor).scale; + const float weightsScale = context->getInputShape(kWeightsTensor).scale; + const float outputScale = context->getOutputShape(kOutputTensor).scale; + bool meetsQuantizedScaleConstraintBeforeV1_2 = (outputScale > inputScale * weightsScale); + + if (!meetsQuantizedScaleConstraintBeforeV1_2) { + NN_RET_CHECK(validateHalVersion(context, HalVersion::V1_2)); + } else { + NN_RET_CHECK(validateHalVersion(context, HalVersion::V1_0)); + } + inExpectedTypes = { OperandType::TENSOR_QUANT8_ASYMM, OperandType::TENSOR_QUANT8_ASYMM,
diff --git a/runtime/test/TestCompliance.cpp b/runtime/test/TestCompliance.cpp index 85df3d0..47700bf 100644 --- a/runtime/test/TestCompliance.cpp +++ b/runtime/test/TestCompliance.cpp
@@ -74,6 +74,7 @@ TEST_AVAILABLE_SINCE_V1_2(sub_v1_2, quant8) TEST_AVAILABLE_SINCE_V1_2(conv2d_v1_2, nchw) TEST_AVAILABLE_SINCE_V1_2(conv2d_v1_2, quant_output_multiplier_gt_1) +TEST_AVAILABLE_SINCE_V1_2(fully_connected_v1_2, quant8_mult_gt_1) TEST_AVAILABLE_SINCE_V1_2(depthwise_conv2d_v1_2, nchw) TEST_AVAILABLE_SINCE_V1_2(depthwise_conv2d_v1_2, quant_output_multiplier_gt_1) TEST_AVAILABLE_SINCE_V1_2(avg_pool_v1_2, nchw)