Add AHardwareBuffer support for NNAPI

   - The main purpose for AHardwareBuffer support is for model inputs &
   outputs.
   - ANeuralNetworks_setOperandValueFromMemory only accepts BLOB mode
   AHardwareBuffer.
   - ANeuralNetworks_set[Input|Output]FromMemory can accepts non-BLOB mode
   AHardwareBuffer. And for non-BLOB mode buffer, the entire buffer will
   be used.
   - There is no guarantee that arbitrary AHardwareBuffer can be used by
   arbitrary devices. The execution must fail if the driver cannot
   consume the buffer.
   - No CPU fallback for AHardwareBuffer except BLOB mode.

Test: mm
Test: NeuralNetworksTest_static
Change-Id: I9d9ac95aea1e56b583c06e4f9c9afdaab1403152
Merged-In: I9d9ac95aea1e56b583c06e4f9c9afdaab1403152
(cherry picked from commit 5777040ee6f93f4060f7efb6cffaf5bff37f99d8)
diff --git a/runtime/ExecutionBuilder.cpp b/runtime/ExecutionBuilder.cpp
index c163f5b..8b04620 100644
--- a/runtime/ExecutionBuilder.cpp
+++ b/runtime/ExecutionBuilder.cpp
@@ -81,15 +81,14 @@
     return ANEURALNETWORKS_NO_ERROR;
 }
 
-int ModelArgumentInfo::setFromTemporaryMemory(const Operand& operand,
-                                              uint32_t poolIndex, uint32_t offset) {
+int ModelArgumentInfo::setFromTemporaryMemory(const Operand& operand, uint32_t poolIndex,
+                                              uint32_t offset) {
     int n = updateDimensionInfo(operand, nullptr);
     if (n != ANEURALNETWORKS_NO_ERROR) {
         return n;
     }
     state = ModelArgumentInfo::MEMORY;
-    locationAndLength =
-            {.poolIndex = poolIndex, .offset = offset, .length = sizeOfData(operand)};
+    locationAndLength = {.poolIndex = poolIndex, .offset = offset, .length = sizeOfData(operand)};
     buffer = nullptr;
     return ANEURALNETWORKS_NO_ERROR;
 }
@@ -126,12 +125,12 @@
     return ANEURALNETWORKS_NO_ERROR;
 }
 
-ExecutionBuilder::ExecutionBuilder(const CompilationBuilder* compilation) :
-        mModel(compilation->mModel),
-        mPlan(&compilation->mPlan),
-        mPartitioning(compilation->mPartitioning),
-        mInputs(mModel->inputCount()),
-        mOutputs(mModel->outputCount()) {
+ExecutionBuilder::ExecutionBuilder(const CompilationBuilder* compilation)
+    : mModel(compilation->mModel),
+      mPlan(&compilation->mPlan),
+      mPartitioning(compilation->mPartitioning),
+      mInputs(mModel->inputCount()),
+      mOutputs(mModel->outputCount()) {
     VLOG(EXECUTION) << "ExecutionBuilder::ExecutionBuilder";
 }
 
@@ -167,7 +166,12 @@
                    << count;
         return ANEURALNETWORKS_BAD_DATA;
     }
-    if (!memory->validateSize(offset, length)) {
+    // Both offset & length must be zero for Non-BLOB format AHardwareBuffer.
+    if (memory->getHidlMemory().name() == "hardware_buffer" && (offset != 0 || length != 0)) {
+        LOG(ERROR) << "ANeuralNetworksExecution_setInputFromMemory has non-zero offset and length"
+                   << " for Non-BLOB format AHardwareBuffer.";
+        return ANEURALNETWORKS_BAD_DATA;
+    } else if (!memory->validateSize(offset, length)) {
         return ANEURALNETWORKS_BAD_DATA;
     }
     // TODO validate the rest
@@ -176,8 +180,8 @@
                                         length);
 }
 
-int ExecutionBuilder::setOutput(uint32_t index, const ANeuralNetworksOperandType* type, void* buffer,
-                                size_t length) {
+int ExecutionBuilder::setOutput(uint32_t index, const ANeuralNetworksOperandType* type,
+                                void* buffer, size_t length) {
     uint32_t count = static_cast<uint32_t>(mOutputs.size());
     if (index >= count) {
         LOG(ERROR) << "ANeuralNetworksExecution_setOutput bad index " << index << " " << count;
@@ -207,7 +211,12 @@
                    << count;
         return ANEURALNETWORKS_BAD_DATA;
     }
-    if (!memory->validateSize(offset, length)) {
+    // Both offset & length must be zero for Non-BLOB format AHardwareBuffer.
+    if (memory->getHidlMemory().name() == "hardware_buffer" && (offset != 0 || length != 0)) {
+        LOG(ERROR) << "ANeuralNetworksExecution_setOutputFromMemory has non-zero offset and length"
+                   << " for Non-BLOB format AHardwareBuffer.";
+        return ANEURALNETWORKS_BAD_DATA;
+    } else if (!memory->validateSize(offset, length)) {
         return ANEURALNETWORKS_BAD_DATA;
     }
     // TODO validate the rest
@@ -281,8 +290,7 @@
 // (2) If unsuccessful, attempt to execute the full model on CPU,
 //     ensure that executionCallback->notify() is called, and return
 //     false.
-static bool cpuFallbackPartial(const ExecutionBuilder* executionBuilder,
-                               const ExecutionPlan* plan,
+static bool cpuFallbackPartial(const ExecutionBuilder* executionBuilder, const ExecutionPlan* plan,
                                std::shared_ptr<ExecutionPlan::Controller> controller,
                                const sp<ExecutionCallback>& executionCallback) {
     NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "cpuFallbackPartial");
@@ -465,15 +473,16 @@
 }
 
 static void setRequestArgumentArray(const std::vector<ModelArgumentInfo>& argumentInfos,
-                                     hidl_vec<RequestArgument>* ioInfos) {
+                                    hidl_vec<RequestArgument>* ioInfos) {
     size_t count = argumentInfos.size();
     ioInfos->resize(count);
     for (size_t i = 0; i < count; i++) {
         const auto& info = argumentInfos[i];
-        (*ioInfos)[i] = { .hasNoValue = info.state == ModelArgumentInfo::HAS_NO_VALUE,
-                          .location = info.locationAndLength,
-                          .dimensions = info.dimensions,
-                        };
+        (*ioInfos)[i] = {
+                .hasNoValue = info.state == ModelArgumentInfo::HAS_NO_VALUE,
+                .location = info.locationAndLength,
+                .dimensions = info.dimensions,
+        };
     }
 }
 
@@ -506,12 +515,10 @@
         case ModelArgumentInfo::UNSPECIFIED:
             break;
         case ModelArgumentInfo::MEMORY: {
-            const uint32_t builderPoolIndex =
-                    builderInputOrOutput.locationAndLength.poolIndex;
+            const uint32_t builderPoolIndex = builderInputOrOutput.locationAndLength.poolIndex;
             const Memory* memory = mExecutionBuilder->mMemories[builderPoolIndex];
             const uint32_t executorPoolIndex = mMemories.add(memory);
-            executorInputOrOutput->locationAndLength.poolIndex =
-                    executorPoolIndex;
+            executorInputOrOutput->locationAndLength.poolIndex = executorPoolIndex;
             break;
         }
     }
@@ -528,7 +535,7 @@
     return inputOrOutputInfo->setFromTemporaryMemory(inputOrOutputOperand, poolIndex, offset);
 }
 
-static void logArguments(const char* kind, const std::vector<ModelArgumentInfo> &args) {
+static void logArguments(const char* kind, const std::vector<ModelArgumentInfo>& args) {
     for (unsigned i = 0; i < args.size(); i++) {
         const auto& arg = args[i];
         std::string prefix = kind + std::string("[") + std::to_string(i) + "] = ";
@@ -538,10 +545,8 @@
                 break;
             case ModelArgumentInfo::MEMORY:
                 VLOG(EXECUTION) << prefix << "MEMORY("
-                                << "pool=" << arg.locationAndLength.poolIndex
-                                << ", "
-                                << "off=" << arg.locationAndLength.offset
-                                << ")";
+                                << "pool=" << arg.locationAndLength.poolIndex << ", "
+                                << "off=" << arg.locationAndLength.offset << ")";
                 break;
             case ModelArgumentInfo::HAS_NO_VALUE:
                 VLOG(EXECUTION) << prefix << "HAS_NO_VALUE";
@@ -590,7 +595,7 @@
         // remove this entire block of code since it is a stale path that is only
         // encountered on an #if-removed code.
         ExecutionPreference preference =
-            static_cast<ExecutionPreference>(ANEURALNETWORKS_PREFER_FAST_SINGLE_ANSWER);
+                static_cast<ExecutionPreference>(ANEURALNETWORKS_PREFER_FAST_SINGLE_ANSWER);
         ErrorStatus prepareLaunchStatus =
                 mDevice->getInterface()->prepareModel(model, preference, preparedModelCallback);
         if (prepareLaunchStatus != ErrorStatus::NONE) {
@@ -698,9 +703,8 @@
     Return<ErrorStatus> callbackStatus = executionCallback->getStatus();
     if (!callbackStatus.isOk() || callbackStatus != ErrorStatus::NONE) {
         VLOG(EXECUTION) << "**Execution failed**";
-        return callbackStatus.isOk()
-                ? convertErrorStatusToResultCode(callbackStatus)
-                : ANEURALNETWORKS_OP_FAILED;
+        return callbackStatus.isOk() ? convertErrorStatusToResultCode(callbackStatus)
+                                     : ANEURALNETWORKS_OP_FAILED;
     }
 
     // Copy the output data from shared memory to the output buffers.
@@ -770,7 +774,7 @@
         for (ModelArgumentInfo& argumentInfo : argumentInfos) {
             if (argumentInfo.state == ModelArgumentInfo::POINTER) {
                 argumentInfo.locationAndLength.poolIndex =
-                            static_cast<uint32_t>(requestPoolInfos.size());
+                        static_cast<uint32_t>(requestPoolInfos.size());
                 argumentInfo.locationAndLength.offset = 0;
                 requestPoolInfos.emplace_back(static_cast<uint8_t*>(argumentInfo.buffer));
             }