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));