address space device direct handle API

bug: 140112486
Change-Id: Ia5f4e36be6c539237d7a677b01e802a39070b73c
diff --git a/shared/OpenglCodecCommon/goldfish_address_space.h b/shared/OpenglCodecCommon/goldfish_address_space.h
index e8170db..b52473f 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space.h
+++ b/shared/OpenglCodecCommon/goldfish_address_space.h
@@ -121,4 +121,40 @@
     GoldfishAddressSpaceBlockProvider m_provider;
 };
 
+// Convenience functions that run address space driver api without wrapping in
+// a class. Useful for when a client wants to manage the driver handle directly
+// (e.g., mmaping() more than one region associated with a single handle will
+// require different lifetime expectations versus GoldfishAddressSpaceBlock).
+
+// We also expose the ping info struct that is shared between host and guest.
+struct goldfish_address_space_ping {
+    uint64_t offset;
+    uint64_t size;
+    uint64_t metadata;
+    uint32_t version;
+    uint32_t wait_fd;
+    uint32_t wait_flags;
+    uint32_t direction;
+};
+
+address_space_handle_t goldfish_address_space_open();
+void goldfish_address_space_close(address_space_handle_t);
+
+bool goldfish_address_space_allocate(
+    address_space_handle_t, size_t size, uint64_t* phys_addr, uint64_t* offset);
+bool goldfish_address_space_free(
+    address_space_handle_t, uint64_t offset);
+
+bool goldfish_address_space_claim_shared(
+    address_space_handle_t, uint64_t offset, uint64_t size);
+bool goldfish_address_space_unclaim_shared(
+    address_space_handle_t, uint64_t offset);
+
+// pgoff is the offset into the page to return in the result
+void* goldfish_address_space_map(
+    address_space_handle_t, uint64_t offset, uint64_t size, uint64_t pgoff = 0);
+void goldfish_address_space_unmap(void* ptr, uint64_t size);
+
+bool goldfish_address_space_ping(address_space_handle_t, struct goldfish_address_space_ping*);
+
 #endif  // #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_ADDRESS_SPACE_H
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_android.impl b/shared/OpenglCodecCommon/goldfish_address_space_android.impl
index e5a84a7..a4ebac2 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_android.impl
+++ b/shared/OpenglCodecCommon/goldfish_address_space_android.impl
@@ -41,16 +41,6 @@
     __u64 phys_addr;
 };
 
-struct goldfish_address_space_ping {
-    __u64 offset;
-    __u64 size;
-    __u64 metadata;
-    __u32 version;
-    __u32 wait_fd;
-    __u32 wait_flags;
-    __u32 direction;
-};
-
 struct goldfish_address_space_claim_shared {
     __u64 offset;
     __u64 size;
@@ -414,3 +404,99 @@
 
     block->replace(NULL);
 }
+
+address_space_handle_t goldfish_address_space_open() {
+    return ::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR);
+}
+
+void goldfish_address_space_close(address_space_handle_t handle) {
+    ::close(handle);
+}
+
+bool goldfish_address_space_allocate(
+    address_space_handle_t handle,
+    size_t size, uint64_t* phys_addr, uint64_t* offset) {
+
+    struct goldfish_address_space_allocate_block request;
+    ::memset(&request, 0, sizeof(request));
+    request.size = size;
+
+    long res = ioctl_allocate(handle, &request);
+
+    if (res) return false;
+
+    *phys_addr = request.phys_addr;
+    *offset = request.offset;
+    return true;
+}
+
+bool goldfish_address_space_free(
+    address_space_handle_t handle, uint64_t offset) {
+
+    long res = ioctl_deallocate(handle, offset);
+
+    if (res) {
+        ALOGE("ioctl_deallocate failed, res=%ld", res);
+        ::abort();
+    }
+
+    return true;
+}
+
+bool goldfish_address_space_claim_shared(
+    address_space_handle_t handle, uint64_t offset, uint64_t size) {
+
+    struct goldfish_address_space_claim_shared request;
+    request.offset = offset;
+    request.size = size;
+    long res = ioctl_claim_shared(handle, &request);
+
+    if (res) return false;
+
+    return true;
+}
+
+bool goldfish_address_space_unclaim_shared(
+        address_space_handle_t handle, uint64_t offset) {
+    long res = ioctl_unclaim_shared(handle, offset);
+    if (res) {
+        ALOGE("ioctl_unclaim_shared failed, res=%ld", res);
+        ::abort();
+    }
+
+    return true;
+}
+
+// pgoff is the offset into the page to return in the result
+void* goldfish_address_space_map(
+    address_space_handle_t handle,
+    uint64_t offset, uint64_t size,
+    uint64_t pgoff) {
+
+    void* res = ::mmap64(0, size, PROT_WRITE, MAP_SHARED, handle, offset);
+
+    if (res == MAP_FAILED) {
+        ALOGE("%s: failed to map. errno: %d\n", __func__, errno);
+        return nullptr;
+    }
+
+    return (void*)(((char*)res) + (uintptr_t)(pgoff & (PAGE_SIZE - 1)));
+}
+
+void goldfish_address_space_unmap(void* ptr, uint64_t size) {
+    void* pagePtr = (void*)(((uintptr_t)ptr) & ~(PAGE_SIZE - 1));
+    ::munmap(pagePtr, size);
+}
+
+bool goldfish_address_space_ping(
+    address_space_handle_t handle,
+    struct goldfish_address_space_ping* ping) {
+    long res = ioctl_ping(handle, ping);
+
+    if (res) {
+        ALOGE("%s: ping failed: errno: %d\n", __func__, errno);
+        return false;
+    }
+
+    return true;
+}
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl b/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
index e1e07f2..c44b10d 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
+++ b/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
@@ -214,3 +214,60 @@
 void GoldfishAddressSpaceHostMemoryAllocator::hostFree(GoldfishAddressSpaceBlock *block)
 {
 }
+
+// TODO: Implement address_space_handle_t interface
+address_space_handle_t goldfish_address_space_open() {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+void goldfish_address_space_close(address_space_handle_t handle) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+bool goldfish_address_space_allocate(
+    address_space_handle_t,
+    size_t, uint64_t*, uint64_t*) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+bool goldfish_address_space_free(
+    address_space_handle_t, uint64_t) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+bool goldfish_address_space_claim_shared(
+    address_space_handle_t, uint64_t, uint64_t) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+bool goldfish_address_space_unclaim_shared(
+    address_space_handle_t, uint64_t) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+// pgoff is the offset into the page to return in the result
+void* goldfish_address_space_map(
+    address_space_handle_t,
+    uint64_t, uint64_t,
+    uint64_t) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+void goldfish_address_space_unmap(void*, uint64_t) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
+
+bool goldfish_address_space_ping(
+    address_space_handle_t handle,
+    struct goldfish_address_space_ping* ping) {
+    ALOGE("%s: not implemented!\n", __func__);
+    abort();
+}
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_host.impl b/shared/OpenglCodecCommon/goldfish_address_space_host.impl
index d2001dd..d5567ad 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_host.impl
+++ b/shared/OpenglCodecCommon/goldfish_address_space_host.impl
@@ -23,6 +23,7 @@
 #include <log/log.h>
 #endif
 
+#include <errno.h>
 #include "goldfish_address_space.h"
 
 namespace {
@@ -287,3 +288,82 @@
     block->replace(NULL);
 }
 
+address_space_handle_t goldfish_address_space_open() {
+    return HostAddressSpaceDevice::get()->open();
+}
+
+void goldfish_address_space_close(address_space_handle_t handle) {
+    HostAddressSpaceDevice::get()->close(handle);
+}
+
+bool goldfish_address_space_allocate(
+    address_space_handle_t handle,
+    size_t size, uint64_t* phys_addr, uint64_t* offset) {
+
+    *offset =
+        HostAddressSpaceDevice::get()->allocBlock(
+            handle, size, phys_addr);
+
+    return true;
+}
+
+bool goldfish_address_space_free(
+    address_space_handle_t handle, uint64_t offset) {
+    HostAddressSpaceDevice::get()->freeBlock(handle, offset);
+    return true;
+}
+
+bool goldfish_address_space_claim_shared(
+    address_space_handle_t handle, uint64_t offset, uint64_t size) {
+
+    int claimRes = HostAddressSpaceDevice::get()->claimShared(
+        handle, offset, size);
+
+    if (claimRes) {
+        ALOGE("%s: failed to claim shared region. Error: %d\n", __func__, claimRes);
+        return false;
+    }
+
+    return true;
+}
+
+bool goldfish_address_space_unclaim_shared(
+        address_space_handle_t handle, uint64_t offset) {
+    HostAddressSpaceDevice::get()->unclaimShared(handle, offset);
+    return true;
+}
+
+// pgoff is the offset into the page to return in the result
+void* goldfish_address_space_map(
+    address_space_handle_t handle,
+    uint64_t offset, uint64_t size,
+    uint64_t pgoff) {
+
+    (void)size;
+
+    void* res = HostAddressSpaceDevice::get()->
+        getHostAddr(
+            HostAddressSpaceDevice::get()->offsetToPhysAddr(offset));
+
+    if (!res) {
+        ALOGE("%s: failed to map. errno: %d\n", __func__, errno);
+        return nullptr;
+    }
+
+    return (void*)(((char*)res) + (uintptr_t)(pgoff & (PAGE_SIZE - 1)));
+}
+
+// same address space
+void goldfish_address_space_unmap(void*, uint64_t) { }
+
+bool goldfish_address_space_ping(
+    address_space_handle_t handle,
+    struct goldfish_address_space_ping* ping) {
+
+    AddressSpaceDevicePingInfo* asHostPingInfo =
+        reinterpret_cast<AddressSpaceDevicePingInfo*>(ping);
+
+    HostAddressSpaceDevice::get()->ping(handle, asHostPingInfo);
+
+    return true;
+}