Merge changes from topic "get-supported-extensions"

* changes:
  Add getSupportedExtensions to NNAPI IDevice
  Define NNAPI Extensions types
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index de249b0..b9fa388 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -76,6 +76,21 @@
     getType() generates (ErrorStatus status, DeviceType type);
 
     /**
+     * Gets information about extensions supported by the driver implementation.
+     *
+     * All extension operations and operands must be fully supported for the
+     * extension to appear in the list of supported extensions.
+     *
+     * @return status Error status of the call, must be:
+     *     - NONE if successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     * @return extensions A list of supported extensions.
+     */
+    getSupportedExtensions()
+        generates (ErrorStatus status, vec<Extension> extensions);
+
+    /**
      * Gets the supported operations in a model.
      *
      * getSupportedOperations indicates which operations of a model are fully
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 4d5f0f4..9e7d8f0 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -73,10 +73,11 @@
      * These fields are located inside Operand's extraParams union, inside the
      * SymmPerChannelQuantParams struct.
      *
-     * An Operand of this type must use 'channelQuant' field of its extraParams
-     * union.
+     * An Operand of this type must use the 'channelQuant' variant of its
+     * extraParams field.
      *
-     * The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0).
+     * The channel dimension of this tensor must be known, i.e.
+     * dimensions[channelDim] must be non-zero.
      *
      * The formula for real values:
      * realValue[..., C, ...] =
@@ -108,10 +109,12 @@
  * The range of operand values in the OperandType enum.
  */
 enum OperandTypeRange : uint32_t {
+    BASE_MIN        = 0,
     FUNDAMENTAL_MIN = 0,
     FUNDAMENTAL_MAX = 12,
-    OEM_MIN     = 10000,
-    OEM_MAX     = 10001,
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10001,
+    BASE_MAX        = 0xFFFF,
 };
 
 /**
@@ -189,10 +192,12 @@
  * The range of values in the OperationType enum.
  */
 enum OperationTypeRange : uint32_t {
+    BASE_MIN        = 0,
     FUNDAMENTAL_MIN = 0,
     FUNDAMENTAL_MAX = 93,
-    OEM_MIN = 10000,
-    OEM_MAX = 10000,
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10000,
+    BASE_MAX        = 0xFFFF,
 };
 
 /**
@@ -221,6 +226,10 @@
 struct Operation {
     /**
      * The operation type.
+     *
+     * Besides the values listed in {@link OperationType}, any value above
+     * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
+     * as an extension type according to {@link Model::extensionNameToPrefix}.
      */
     OperationType type;
 
@@ -247,21 +256,16 @@
     uint32_t channelDim;
 };
 
-// TODO(slavash): Operand Extension support
-// /**
-//  * Parameters for an unknown (as of 1.2) operand extension. This is
-//  * a vendor-specific extension or a platform extension (backport of
-//  * functionality from newer NNAPI interface).
-//  */
-// struct OperandParamsUnknown {
-// };
-
 /**
  * Describes one operand of the model's graph.
  */
 struct Operand {
     /**
-     * Data type of the operand.
+     * The data type.
+     *
+     * Besides the values listed in {@link OperandType}, any value above
+     * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
+     * as an extension type according to {@link Model::extensionNameToPrefix}.
      */
     OperandType type;
 
@@ -351,25 +355,28 @@
     DataLocation location;
 
     /**
-     * Union of extra parameters, used by some types of Operands that need additional
-     * information for the complete definition of an Operand.
+     * Additional parameters specific to a particular operand type.
      */
     safe_union ExtraParams {
        /**
-        * Placeholder for operand with no extra parameters.
+        * No additional parameters.
         */
        Monostate none;
 
        /**
-        * Used with TENSOR_QUANT8_SYMM_PER_CHANNEL operand type.
+        * Symmetric per-channel quantization parameters.
+        *
+        * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
         */
        SymmPerChannelQuantParams channelQuant;
 
-       // TODO(slavash): Operand Extension support
-       // /**
-       //  * Used with Extension operand type.
-       //  */
-       // OperandParamsUnknown unknown;
+       /**
+        * Extension operand parameters.
+        *
+        * The framework treats this as an opaque data blob.
+        * The format is up to individual extensions.
+        */
+       vec<uint8_t> extension;
     } extraParams;
 };
 
@@ -432,6 +439,63 @@
      * range and precision of the IEEE 754 32-bit floating-point format.
      */
     bool relaxComputationFloat32toFloat16;
+
+    /**
+     * The mapping between extension names and prefixes of operand and
+     * operation type values.
+     *
+     * An operand or operation whose numeric type value is above
+     * {@link OperandTypeRange::BASE_MAX} or
+     * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
+     * as an extension operand. The low
+     * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
+     * correspond to the value within the extension and the high
+     * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
+     * the "prefix", which maps uniquely to the extension name.
+     *
+     * For example, if a model contains an operation whose value is
+     * 0xAAAABBBB and extensionNameToPrefix contains an entry with
+     * prefix=0xAAAA and name="vendor.test.test_extension", then
+     * the operation should be interpreted as the operation 0xBBBB
+     * of the extension named vendor.test.test_extension.
+     *
+     * This is a one-to-one correspondence. That is, there must be at most one
+     * prefix corresponding to each extension name and at most one extension
+     * name corresponding to each prefix.
+     */
+    vec<ExtensionNameAndPrefix> extensionNameToPrefix;
+
+    /**
+     * A correspondence between an extension name and a prefix of operand and
+     * operation type values.
+     */
+    struct ExtensionNameAndPrefix {
+        /**
+         * The extension name.
+         *
+         * See {@link Extension::name}.
+         */
+        string name;
+
+        /**
+         * The unique extension identifier within the model.
+         *
+         * See {@link Model::extensionNameToPrefix}.
+         */
+        uint16_t prefix;
+    };
+
+    /**
+     * Numeric values of extension operand and operation types have the
+     * following structure:
+     * - 16 high bits represent the "prefix", which corresponds uniquely to the
+     *   extension name.
+     * - 16 low bits represent the type ID within the extension.
+     */
+    enum ExtensionTypeEncoding : uint8_t {
+        HIGH_BITS_PREFIX = 16,
+        LOW_BITS_TYPE = 16,
+    };
 };
 
 /**
@@ -685,3 +749,43 @@
      */
     Timing executionTiming;
 };
+
+/**
+ * Information about an extension.
+ */
+struct Extension {
+    /**
+     * The extension name.
+     *
+     * The name must start with the reverse domain name of the vendor.
+     * Example: com.google.test_extension
+     */
+    string name;
+
+    /**
+     * Information about an extension operand type.
+     */
+    struct OperandTypeInformation {
+        /**
+         * The extension operand type.
+         */
+        uint16_t type;
+
+        /**
+         * Indicates whether the extension operand type represents a tensor or
+         * a scalar.
+         */
+        bool isTensor;
+
+        /**
+         * The byte size of the operand (if scalar) or of a single element (if
+         * tensor).
+         */
+        uint32_t byteSize;
+    };
+
+    /**
+     * Information about operand types defined by the extension.
+     */
+    vec<OperandTypeInformation> operandTypes;
+};
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 8c3ad15..0eec365 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -55,6 +55,23 @@
     });
     EXPECT_TRUE(ret.isOk());
 }
+
+// device supported extensions test
+TEST_F(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) {
+    Return<void> ret = device->getSupportedExtensions(
+            [](ErrorStatus status, const hidl_vec<Extension>& extensions) {
+                EXPECT_EQ(ErrorStatus::NONE, status);
+                for (auto& extension : extensions) {
+                    std::string extensionName = extension.name;
+                    EXPECT_FALSE(extensionName.empty());
+                    EXPECT_NE(extensionName.find("."), std::string::npos)
+                            << "Extension name must start with the reverse domain name of the "
+                               "vendor";
+                }
+            });
+    EXPECT_TRUE(ret.isOk());
+}
+
 }  // namespace functional
 }  // namespace vts
 }  // namespace V1_2