Cleanup NNAPI runtime Memory objects

Prior to this CL, runtime Memory* objects were default constructed and
set to a value later. Rebinding the value led to multiple bugs in the
past and made the Memory* objects prone to data races. This CL addresses
these issues by determining all values in the Memory* objects' factory
methods, and making the Memory* objects immutable after construction.

This CL also untangles some of the inheritance hierarchy. Prior to this
CL, all MemoryFd and MemoryAHWB inherited from Memory, which was
effectively ashmem-based memory. This CL separates MemoryAshmem into its
own, unique class type, and has a common base Memory class. This
reorganization also uncovered that getPointer was only used in the
runtime on ashmem-based memory, and removes the unused getPointer
methods.

Finally, this CL improves documentation of NeuralNetworks.h in two ways:
1) Fixes the typo "ANeuralNetworksMemory_createFromAHardwarBuffer"
2) Documents the missing lifetime constraints of
   ANeuralNetworksMemory_createFromAHardwareBuffer

Fixes: 138852228
Fixes: 69632863
Fixes: 69633035
Fixes: 129572123
Fixes: 132323765
Fixes: 139213289
Test: mma
Test: atest NeuralNetworksTest_static
Test: atest CtsNNAPITestCases
Change-Id: I49a2356d6b8fc38e501d8e37ba8a8893f3e91395
Merged-In: I49a2356d6b8fc38e501d8e37ba8a8893f3e91395
(cherry picked from commit 008caeab69787b8978e874f8fb3811e2400f5d55)
diff --git a/runtime/Memory.cpp b/runtime/Memory.cpp
index 20fabfa..6e972c6 100644
--- a/runtime/Memory.cpp
+++ b/runtime/Memory.cpp
@@ -18,6 +18,8 @@
 
 #include "Memory.h"
 
+#include <memory>
+#include <utility>
 #include "ExecutionBurstController.h"
 #include "MemoryUtils.h"
 #include "Utils.h"
@@ -27,6 +29,8 @@
 
 using namespace hal;
 
+Memory::Memory(hidl_memory memory) : kHidlMemory(std::move(memory)) {}
+
 Memory::~Memory() {
     for (const auto [ptr, weakBurst] : mUsedBy) {
         if (const std::shared_ptr<ExecutionBurstController> burst = weakBurst.lock()) {
@@ -35,23 +39,12 @@
     }
 }
 
-int Memory::create(uint32_t size) {
-    mHidlMemory = allocateSharedMemory(size);
-    mMemory = mapMemory(mHidlMemory);
-    if (mMemory == nullptr) {
-        LOG(ERROR) << "Memory::create failed";
-        return ANEURALNETWORKS_OUT_OF_MEMORY;
-    }
-    return ANEURALNETWORKS_NO_ERROR;
-}
-
 bool Memory::validateSize(uint32_t offset, uint32_t length) const {
-    if (offset + length > mHidlMemory.size()) {
+    if (offset + length > kHidlMemory.size()) {
         LOG(ERROR) << "Request size larger than the memory size.";
         return false;
-    } else {
-        return true;
     }
+    return true;
 }
 
 intptr_t Memory::getKey() const {
@@ -63,83 +56,98 @@
     mUsedBy.emplace(burst.get(), burst);
 }
 
-MemoryFd::~MemoryFd() {
-    // Unmap the memory.
-    if (mMapping) {
-        munmap(mMapping, mHidlMemory.size());
+std::pair<int, std::unique_ptr<MemoryAshmem>> MemoryAshmem::create(uint32_t size) {
+    hidl_memory hidlMemory = allocateSharedMemory(size);
+    sp<IMemory> mapped = mapMemory(hidlMemory);
+    if (mapped == nullptr || mapped->getPointer() == nullptr) {
+        LOG(ERROR) << "Memory::create failed";
+        return {ANEURALNETWORKS_OUT_OF_MEMORY, nullptr};
     }
-    // Delete the native_handle.
-    if (mHandle) {
-        int fd = mHandle->data[0];
-        if (fd != -1) {
-            close(fd);
-        }
-        native_handle_delete(mHandle);
-    }
+    return {ANEURALNETWORKS_NO_ERROR,
+            std::make_unique<MemoryAshmem>(std::move(mapped), std::move(hidlMemory))};
 }
 
-int MemoryFd::set(size_t size, int prot, int fd, size_t offset) {
+uint8_t* MemoryAshmem::getPointer() const {
+    return static_cast<uint8_t*>(static_cast<void*>(kMappedMemory->getPointer()));
+}
+
+MemoryAshmem::MemoryAshmem(sp<IMemory> mapped, hidl_memory memory)
+    : Memory(std::move(memory)), kMappedMemory(std::move(mapped)) {}
+
+std::pair<int, std::unique_ptr<MemoryFd>> MemoryFd::create(size_t size, int prot, int fd,
+                                                           size_t offset) {
     if (size == 0 || fd < 0) {
         LOG(ERROR) << "Invalid size or fd";
-        return ANEURALNETWORKS_BAD_DATA;
+        return {ANEURALNETWORKS_BAD_DATA, nullptr};
     }
+
+    // Duplicate the file descriptor so MemoryFd owns its own version.
     int dupfd = dup(fd);
     if (dupfd == -1) {
         LOG(ERROR) << "Failed to dup the fd";
-        return ANEURALNETWORKS_UNEXPECTED_NULL;
+        // TODO(b/120417090): is ANEURALNETWORKS_UNEXPECTED_NULL the correct
+        // error to return here?
+        return {ANEURALNETWORKS_UNEXPECTED_NULL, nullptr};
     }
 
-    if (mMapping) {
-        if (munmap(mMapping, mHidlMemory.size()) != 0) {
-            LOG(ERROR) << "Failed to remove the existing mapping";
-            // This is not actually fatal.
-        }
-        mMapping = nullptr;
-    }
-    if (mHandle) {
-        native_handle_delete(mHandle);
-    }
-    mHandle = native_handle_create(1, 3);
-    if (mHandle == nullptr) {
+    // Create a temporary native handle to own the dupfd.
+    native_handle_t* nativeHandle = native_handle_create(1, 3);
+    if (nativeHandle == nullptr) {
         LOG(ERROR) << "Failed to create native_handle";
-        return ANEURALNETWORKS_UNEXPECTED_NULL;
+        // TODO(b/120417090): is ANEURALNETWORKS_UNEXPECTED_NULL the correct
+        // error to return here?
+        return {ANEURALNETWORKS_UNEXPECTED_NULL, nullptr};
     }
-    mHandle->data[0] = dupfd;
-    mHandle->data[1] = prot;
-    mHandle->data[2] = (int32_t)(uint32_t)(offset & 0xffffffff);
-#if defined(__LP64__)
-    mHandle->data[3] = (int32_t)(uint32_t)(offset >> 32);
-#else
-    mHandle->data[3] = 0;
-#endif
-    mHidlMemory = hidl_memory("mmap_fd", mHandle, size);
-    return ANEURALNETWORKS_NO_ERROR;
+    nativeHandle->data[0] = dupfd;
+    nativeHandle->data[1] = prot;
+    const uint64_t bits = static_cast<uint64_t>(offset);
+    nativeHandle->data[2] = (int32_t)(uint32_t)(bits & 0xffffffff);
+    nativeHandle->data[3] = (int32_t)(uint32_t)(bits >> 32);
+
+    // Create a hidl_handle which owns the native handle and fd so that we don't
+    // have to manually clean either the native handle or the fd.
+    hardware::hidl_handle hidlHandle;
+    hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true);
+
+    // Push the hidl_handle into a hidl_memory object. The hidl_memory object is
+    // responsible for cleaning the hidl_handle, the native handle, and the fd.
+    hidl_memory hidlMemory = hidl_memory("mmap_fd", std::move(hidlHandle), size);
+
+    return {ANEURALNETWORKS_NO_ERROR, std::make_unique<MemoryFd>(std::move(hidlMemory))};
 }
 
-int MemoryFd::getPointer(uint8_t** buffer) const {
-    if (mMapping) {
-        *buffer = mMapping;
-        return ANEURALNETWORKS_NO_ERROR;
-    }
+MemoryFd::MemoryFd(hidl_memory memory) : Memory(std::move(memory)) {}
 
-    if (mHandle == nullptr) {
-        LOG(ERROR) << "Memory not initialized";
-        return ANEURALNETWORKS_UNEXPECTED_NULL;
-    }
-
-    int fd = mHandle->data[0];
-    int prot = mHandle->data[1];
-    size_t offset = getSizeFromInts(mHandle->data[2], mHandle->data[3]);
-    void* data = mmap(nullptr, mHidlMemory.size(), prot, MAP_SHARED, fd, offset);
-    if (data == MAP_FAILED) {
-        LOG(ERROR) << "MemoryFd::getPointer(): Can't mmap the file descriptor.";
-        return ANEURALNETWORKS_UNMAPPABLE;
+std::pair<int, std::unique_ptr<MemoryAHWB>> MemoryAHWB::create(const AHardwareBuffer& ahwb) {
+    AHardwareBuffer_Desc bufferDesc;
+    AHardwareBuffer_describe(&ahwb, &bufferDesc);
+    const native_handle_t* handle = AHardwareBuffer_getNativeHandle(&ahwb);
+    hidl_memory hidlMemory;
+    if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
+        hidlMemory = hidl_memory("hardware_buffer_blob", handle, bufferDesc.width);
     } else {
-        mMapping = *buffer = static_cast<uint8_t*>(data);
-        return ANEURALNETWORKS_NO_ERROR;
+        // memory size is not used.
+        hidlMemory = hidl_memory("hardware_buffer", handle, 0);
     }
+
+    std::unique_ptr<MemoryAHWB> memory =
+            std::make_unique<MemoryAHWB>(bufferDesc, std::move(hidlMemory));
+    return {ANEURALNETWORKS_NO_ERROR, std::move(memory)};
+};
+
+bool MemoryAHWB::validateSize(uint32_t offset, uint32_t length) const {
+    // validateSize should only be called on BLOB mode buffer.
+    if (!kBlobMode) {
+        LOG(ERROR) << "Invalid AHARDWAREBUFFER_FORMAT, must be AHARDWAREBUFFER_FORMAT_BLOB.";
+        return false;
+    }
+    // Use normal validation.
+    return Memory::validateSize(offset, length);
 }
 
+MemoryAHWB::MemoryAHWB(const AHardwareBuffer_Desc& desc, hidl_memory memory)
+    : Memory(std::move(memory)), kBlobMode(desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {}
+
 uint32_t MemoryTracker::add(const Memory* memory) {
     VLOG(MODEL) << __func__ << "(" << SHOW_IF_DEBUG(memory) << ")";
     // See if we already have this memory. If so,