memory -> hidl_memory and pointer -> hidl_pointer

Test: hidl_test
Change-Id: Id71c742867be01e80cd48f689c0c619f6b647aac
diff --git a/Android.bp b/Android.bp
index ad0e933..856393c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -38,8 +38,10 @@
         "GenericBinder.cpp",
         "HandleType.cpp",
         "Interface.cpp",
+        "MemoryType.cpp",
         "Method.cpp",
         "NamedType.cpp",
+        "PointerType.cpp",
         "PredefinedType.cpp",
         "RefType.cpp",
         "ScalarType.cpp",
diff --git a/MemoryType.cpp b/MemoryType.cpp
new file mode 100644
index 0000000..e85fc87
--- /dev/null
+++ b/MemoryType.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MemoryType.h"
+
+#include <hidl-util/Formatter.h>
+#include <android-base/logging.h>
+
+namespace android {
+
+MemoryType::MemoryType() {}
+
+void MemoryType::addNamedTypesToSet(std::set<const FQName> &) const {
+    // do nothing
+}
+
+std::string MemoryType::getCppType(StorageMode mode,
+                                   bool specifyNamespaces) const {
+    const std::string base =
+          std::string(specifyNamespaces ? "::android::hardware::" : "")
+        + "hidl_memory";
+
+    switch (mode) {
+        case StorageMode_Stack:
+            return base;
+
+        case StorageMode_Argument:
+            return "const " + base + "&";
+
+        case StorageMode_Result:
+            return "const " + base + "*";
+    }
+}
+
+std::string MemoryType::getVtsType() const {
+    return "TYPE_MEMORY";
+}
+
+void MemoryType::emitReaderWriter(
+        Formatter &out,
+        const std::string &name,
+        const std::string &parcelObj,
+        bool parcelObjIsPointer,
+        bool isReader,
+        ErrorMode mode) const {
+    const std::string parentName = "_hidl_" + name + "_parent";
+    out << "size_t " << parentName << ";\n\n";
+
+    const std::string parcelObjDeref =
+        parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+    if (isReader) {
+        out << name
+            << " = (const ::android::hardware::hidl_memory *)"
+            << parcelObjDeref
+            << "readBuffer("
+            << "&"
+            << parentName
+            << ");\n";
+
+        out << "if ("
+            << name
+            << " == nullptr) {\n";
+
+        out.indent();
+
+        out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
+        handleError2(out, mode);
+
+        out.unindent();
+        out << "}\n\n";
+    } else {
+        out << "_hidl_err = "
+            << parcelObjDeref
+            << "writeBuffer(&"
+            << name
+            << ", sizeof("
+            << name
+            << "), &"
+            << parentName
+            << ");\n";
+
+        handleError(out, mode);
+    }
+
+    emitReaderWriterEmbedded(
+            out,
+            0 /* depth */,
+            name,
+            name /* sanitizedName */,
+            isReader /* nameIsPointer */,
+            parcelObj,
+            parcelObjIsPointer,
+            isReader,
+            mode,
+            parentName,
+            "0 /* parentOffset */");
+}
+
+void MemoryType::emitReaderWriterEmbedded(
+        Formatter &out,
+        size_t /* depth */,
+        const std::string &name,
+        const std::string & /*sanitizedName*/,
+        bool nameIsPointer,
+        const std::string &parcelObj,
+        bool parcelObjIsPointer,
+        bool isReader,
+        ErrorMode mode,
+        const std::string &parentName,
+        const std::string &offsetText) const {
+    emitReaderWriterEmbeddedForTypeName(
+            out,
+            name,
+            nameIsPointer,
+            parcelObj,
+            parcelObjIsPointer,
+            isReader,
+            mode,
+            parentName,
+            offsetText,
+            "::android::hardware::hidl_memory",
+            "" /* childName */,
+            "::android::hardware");
+}
+
+bool MemoryType::needsEmbeddedReadWrite() const {
+    return true;
+}
+
+bool MemoryType::resultNeedsDeref() const {
+    return true;
+}
+
+bool MemoryType::isJavaCompatible() const {
+    return false;
+}
+
+void MemoryType::getAlignmentAndSize(size_t *align, size_t *size) const {
+    *align = *size = 8;
+}
+
+status_t MemoryType::emitVtsTypeDeclarations(Formatter &out) const {
+    out << "type: " << getVtsType() << "\n";
+    return OK;
+}
+
+}  // namespace android
+
diff --git a/MemoryType.h b/MemoryType.h
new file mode 100644
index 0000000..42992c2
--- /dev/null
+++ b/MemoryType.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEMORY_TYPE_H_
+
+#define MEMORY_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct MemoryType : public Type {
+    MemoryType();
+
+    void addNamedTypesToSet(std::set<const FQName> &set) const override;
+
+    std::string getCppType(
+            StorageMode mode,
+            bool specifyNamespaces) const override;
+
+    std::string getVtsType() const override;
+
+    void emitReaderWriter(
+            Formatter &out,
+            const std::string &name,
+            const std::string &parcelObj,
+            bool parcelObjIsPointer,
+            bool isReader,
+            ErrorMode mode) const override;
+
+    void emitReaderWriterEmbedded(
+            Formatter &out,
+            size_t depth,
+            const std::string &name,
+            const std::string &sanitizedName,
+            bool nameIsPointer,
+            const std::string &parcelObj,
+            bool parcelObjIsPointer,
+            bool isReader,
+            ErrorMode mode,
+            const std::string &parentName,
+            const std::string &offsetText) const override;
+
+    bool needsEmbeddedReadWrite() const override;
+    bool resultNeedsDeref() const override;
+
+    bool isJavaCompatible() const override;
+
+    void getAlignmentAndSize(size_t *align, size_t *size) const override;
+
+    status_t emitVtsTypeDeclarations(Formatter &out) const override;
+};
+
+}  // namespace android
+
+#endif  // MEMORY_TYPE_H_
+
diff --git a/Method.cpp b/Method.cpp
index e3db869..502591c 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -216,6 +216,10 @@
         return typedVar;
     }
 
+    if (typedVar->type().isPointer()) {
+        return typedVar;
+    }
+
     return nullptr;
 }
 
diff --git a/PointerType.cpp b/PointerType.cpp
new file mode 100644
index 0000000..14bc010
--- /dev/null
+++ b/PointerType.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PointerType.h"
+
+#include <hidl-util/Formatter.h>
+#include <android-base/logging.h>
+
+namespace android {
+
+PointerType::PointerType() {}
+
+bool PointerType::isPointer() const {
+    return true;
+}
+
+void PointerType::addNamedTypesToSet(std::set<const FQName> &) const {
+    // do nothing
+}
+
+std::string PointerType::getCppType(StorageMode /* mode */,
+                                   bool /* specifyNamespaces */) const {
+    return "void*";
+}
+
+std::string PointerType::getVtsType() const {
+    return "TYPE_POINTER";
+}
+
+void PointerType::emitReaderWriter(
+        Formatter& out,
+        const std::string& /* name */,
+        const std::string& /* parcelObj */,
+        bool /* parcelObjIsPointer */,
+        bool /* isReader */,
+        ErrorMode /* mode */) const {
+    out << "LOG_ALWAYS_FATAL(\"Pointer is only supported in passthrough mode\");\n";
+}
+
+bool PointerType::needsEmbeddedReadWrite() const {
+    return false;
+}
+
+bool PointerType::resultNeedsDeref() const {
+    return false;
+}
+
+bool PointerType::isJavaCompatible() const {
+    return false;
+}
+
+void PointerType::getAlignmentAndSize(size_t *align, size_t *size) const {
+    *align = *size = 0; // this object should only be used in passthrough mode
+}
+
+status_t PointerType::emitVtsTypeDeclarations(Formatter &out) const {
+    out << "type: " << getVtsType() << "\n";
+    return OK;
+}
+
+}  // namespace android
+
diff --git a/PointerType.h b/PointerType.h
new file mode 100644
index 0000000..242cc63
--- /dev/null
+++ b/PointerType.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef POINTER_TYPE_H_
+
+#define POINTER_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct PointerType : public Type {
+    PointerType();
+
+    bool isPointer() const override;
+
+    void addNamedTypesToSet(std::set<const FQName> &set) const override;
+
+    std::string getCppType(
+            StorageMode mode,
+            bool specifyNamespaces) const override;
+
+    std::string getVtsType() const override;
+
+    void emitReaderWriter(
+            Formatter &out,
+            const std::string &name,
+            const std::string &parcelObj,
+            bool parcelObjIsPointer,
+            bool isReader,
+            ErrorMode mode) const override;
+
+    bool needsEmbeddedReadWrite() const override;
+    bool resultNeedsDeref() const override;
+
+    bool isJavaCompatible() const override;
+
+    void getAlignmentAndSize(size_t *align, size_t *size) const override;
+
+    status_t emitVtsTypeDeclarations(Formatter &out) const override;
+};
+
+}  // namespace android
+
+#endif  // POINTER_TYPE_H_
+
diff --git a/Type.cpp b/Type.cpp
index 47cea08..924caed 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -74,6 +74,10 @@
     return false;
 }
 
+bool Type::isPointer() const {
+    return false;
+}
+
 const ScalarType *Type::resolveToScalarType() const {
     return NULL;
 }
diff --git a/Type.h b/Type.h
index 35374c7..1983cfb 100644
--- a/Type.h
+++ b/Type.h
@@ -35,14 +35,15 @@
     Type();
     virtual ~Type();
 
-    virtual bool isScope() const;
-    virtual bool isInterface() const;
-    virtual bool isEnum() const;
-    virtual bool isTypeDef() const;
-    virtual bool isBinder() const;
-    virtual bool isNamedType() const;
-    virtual bool isCompoundType() const;
     virtual bool isArray() const;
+    virtual bool isBinder() const;
+    virtual bool isCompoundType() const;
+    virtual bool isEnum() const;
+    virtual bool isInterface() const;
+    virtual bool isNamedType() const;
+    virtual bool isPointer() const;
+    virtual bool isScope() const;
+    virtual bool isTypeDef() const;
     virtual bool isVector() const;
 
     virtual const ScalarType *resolveToScalarType() const;
diff --git a/generateCppImpl.cpp b/generateCppImpl.cpp
index 939bcc2..e9cd776 100644
--- a/generateCppImpl.cpp
+++ b/generateCppImpl.cpp
@@ -149,6 +149,7 @@
     }
 
     out << "using ::android::hardware::hidl_array;\n";
+    out << "using ::android::hardware::hidl_memory;\n";
     out << "using ::android::hardware::hidl_string;\n";
     out << "using ::android::hardware::hidl_vec;\n";
     out << "using ::android::hardware::Return;\n";
diff --git a/hidl-gen_l.ll b/hidl-gen_l.ll
index ab743d5..05a91fd 100644
--- a/hidl-gen_l.ll
+++ b/hidl-gen_l.ll
@@ -36,7 +36,9 @@
 #include "ConstantExpression.h"
 #include "EnumType.h"
 #include "HandleType.h"
+#include "MemoryType.h"
 #include "Method.h"
+#include "PointerType.h"
 #include "ScalarType.h"
 #include "StringType.h"
 #include "VectorType.h"
@@ -109,6 +111,8 @@
 "double"		{ SCALAR_TYPE(KIND_DOUBLE); }
 
 "handle"		{ yylval->type = new HandleType; return token::TYPE; }
+"memory"		{ yylval->type = new MemoryType; return token::TYPE; }
+"pointer"		{ yylval->type = new PointerType; return token::TYPE; }
 "string"		{ yylval->type = new StringType; return token::TYPE; }
 
 "MQDescriptorSync" { yylval->type = new PredefinedType("::android::hardware", "MQDescriptorSync"); return token::TYPE; }
diff --git a/test/Android.bp b/test/Android.bp
index aea10c0..a8908dd 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -13,6 +13,7 @@
         "libcutils",
         "libhidlbase",
         "libhidltransport",
+        "libhidlmemory",
         "libfootest",
         "libhwbinder",
         "libnativehelper",
@@ -22,6 +23,8 @@
         "android.hardware.tests.bar@1.0",
         "android.hardware.tests.inheritance@1.0",
         "android.hardware.tests.pointer@1.0",
+        "android.hardware.tests.memory@1.0",
+        "android.hidl.memory@1.0"
     ],
     static_libs: ["libgtest"],
 
diff --git a/test/main.cpp b/test/main.cpp
index 85b94cd..636dca2 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -4,6 +4,9 @@
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <android/hidl/manager/1.0/IServiceNotification.h>
 
+#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+
 // TODO(b/32756130): remove
 #include <android/hardware/tests/foo/1.0/BnSimple.h>
 
@@ -14,6 +17,7 @@
 #include <android/hardware/tests/inheritance/1.0/IGrandparent.h>
 #include <android/hardware/tests/inheritance/1.0/IParent.h>
 #include <android/hardware/tests/inheritance/1.0/IChild.h>
+#include <android/hardware/tests/memory/1.0/IMemoryTest.h>
 #include <android/hardware/tests/pointer/1.0/IGraph.h>
 #include <android/hardware/tests/pointer/1.0/IPointer.h>
 
@@ -42,6 +46,7 @@
 #include <hidl-test/PointerHelper.h>
 
 #include <hidl/Status.h>
+#include <hidlmemory/mapping.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/ProcessState.h>
 
@@ -81,15 +86,19 @@
 using ::android::hardware::tests::inheritance::V1_0::IChild;
 using ::android::hardware::tests::pointer::V1_0::IGraph;
 using ::android::hardware::tests::pointer::V1_0::IPointer;
+using ::android::hardware::tests::memory::V1_0::IMemoryTest;
 using ::android::hardware::IPCThreadState;
 using ::android::hardware::ProcessState;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
 using ::android::hidl::manager::V1_0::IServiceManager;
 using ::android::hidl::manager::V1_0::IServiceNotification;
+using ::android::hidl::memory::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
 using ::android::sp;
 using ::android::to_string;
 using ::android::Mutex;
@@ -240,6 +249,8 @@
 
 public:
     sp<IServiceManager> manager;
+    sp<IAllocator> ashmemAllocator;
+    sp<IMemoryTest> memoryTest;
     sp<IFetcher> fetcher;
     sp<IFoo> foo;
     sp<IBar> bar;
@@ -266,6 +277,14 @@
         // getStub is true if we are in passthrough mode to skip checking
         // binderized server, false for binderized mode.
 
+        ashmemAllocator = IAllocator::getService("ashmem", gMode == PASSTHROUGH /* getStub */);
+        ASSERT_NE(ashmemAllocator, nullptr);
+        ASSERT_EQ(ashmemAllocator->isRemote(), gMode == BINDERIZED);
+
+        memoryTest = IMemoryTest::getService("memory", gMode == PASSTHROUGH /* getStub */);
+        ASSERT_NE(memoryTest, nullptr);
+        ASSERT_EQ(memoryTest->isRemote(), gMode == BINDERIZED);
+
         fetcher = IFetcher::getService("fetcher", gMode == PASSTHROUGH /* getStub */);
         ASSERT_NE(fetcher, nullptr);
         ASSERT_EQ(fetcher->isRemote(), gMode == BINDERIZED);
@@ -327,6 +346,8 @@
         ALOGI("Environment setup beginning...");
 
         size_t i = 0;
+        addServer<IAllocator>("ashmem");
+        addServer<IMemoryTest>("memory");
         addServer<IChild>("child");
         addServer<IParent>("parent");
         addServer<IFetcher>("fetcher");
@@ -344,6 +365,8 @@
 class HidlTest : public ::testing::Test {
 public:
     sp<IServiceManager> manager;
+    sp<IAllocator> ashmemAllocator;
+    sp<IMemoryTest> memoryTest;
     sp<IFetcher> fetcher;
     sp<IFoo> foo;
     sp<IBar> bar;
@@ -361,6 +384,8 @@
             env = gPassthroughEnvironment;
         }
         manager = env->manager;
+        ashmemAllocator = env->ashmemAllocator;
+        memoryTest = env->memoryTest;
         fetcher = env->fetcher;
         foo = env->foo;
         bar = env->bar;
@@ -525,6 +550,45 @@
     }
 }
 
+TEST_F(HidlTest, TestSharedMemory) {
+    const uint8_t kValue = 0xCA;
+    hidl_memory mem_copy;
+    EXPECT_OK(ashmemAllocator->allocate(1024, [&](bool success, const hidl_memory& mem) {
+        EXPECT_EQ(success, true);
+
+        sp<IMemory> memory = mapMemory(mem);
+
+        EXPECT_NE(memory, nullptr);
+
+        uint8_t* data = static_cast<uint8_t*>(static_cast<void*>(memory->getPointer()));
+        EXPECT_NE(data, nullptr);
+
+        EXPECT_EQ(memory->getSize(), mem.size());
+
+        memory->update();
+        memset(data, 0, memory->getSize());
+        memory->commit();
+
+        mem_copy = mem;
+        memoryTest->fillMemory(mem, kValue);
+        for (size_t i = 0; i < mem.size(); i++) {
+            EXPECT_EQ(kValue, data[i]);
+        }
+    }));
+
+    // Test the memory persists after the call
+    sp<IMemory> memory = mapMemory(mem_copy);
+
+    EXPECT_NE(memory, nullptr);
+
+    uint8_t* data = static_cast<uint8_t*>(static_cast<void*>(memory->getPointer()));
+    EXPECT_NE(data, nullptr);
+
+    for (size_t i = 0; i < mem_copy.size(); i++) {
+        EXPECT_EQ(kValue, data[i]);
+    }
+}
+
 TEST_F(HidlTest, FooDoThisTest) {
     ALOGI("CLIENT call doThis.");
     EXPECT_OK(foo->doThis(1.0f));