Merge "emitEnumBitwiseOperator takes operator parameter."
diff --git a/ArrayType.cpp b/ArrayType.cpp
index a506e0c..14e375a 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -350,7 +350,7 @@
out << "{\n";
out.indent();
- out << "HwBlob _hidl_blob = ";
+ out << "android.os.HwBlob _hidl_blob = ";
if (isReader) {
out << parcelObj
@@ -359,7 +359,7 @@
size_t align, size;
getAlignmentAndSize(&align, &size);
- out << "new HwBlob("
+ out << "new android.os.HwBlob("
<< size
<< " /* size */);\n";
}
diff --git a/CompoundType.cpp b/CompoundType.cpp
index e3ed250..2715f50 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -28,6 +28,10 @@
mFields(NULL) {
}
+CompoundType::Style CompoundType::style() const {
+ return mStyle;
+}
+
bool CompoundType::setFields(
std::vector<CompoundField *> *fields, std::string *errorMsg) {
mFields = fields;
@@ -428,25 +432,25 @@
out << "\n";
}
- out << "public final void readFromParcel(HwParcel parcel) {\n";
+ out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
out.indent();
- out << "HwBlob blob = parcel.readBuffer();\n";
+ out << "android.os.HwBlob blob = parcel.readBuffer();\n";
out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
out.unindent();
out << "}\n\n";
////////////////////////////////////////////////////////////////////////////
- out << "public static final ArrayList<"
+ out << "public static final java.util.ArrayList<"
<< localName()
- << "> readVectorFromParcel(HwParcel parcel) {\n";
+ << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
out.indent();
- out << "ArrayList<"
+ out << "java.util.ArrayList<"
<< localName()
- << "> _hidl_vec = new ArrayList();\n";
+ << "> _hidl_vec = new java.util.ArrayList();\n";
- out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
+ out << "android.os.HwBlob _hidl_blob = parcel.readBuffer();\n\n";
VectorType::EmitJavaFieldReaderWriterForElementType(
out,
@@ -467,7 +471,7 @@
out << "public final void readEmbeddedFromParcel(\n";
out.indent(2);
- out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
+ out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
out.unindent();
size_t offset = 0;
@@ -500,10 +504,10 @@
size_t structAlign, structSize;
getAlignmentAndSize(&structAlign, &structSize);
- out << "public final void writeToParcel(HwParcel parcel) {\n";
+ out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
out.indent();
- out << "HwBlob _hidl_blob = new HwBlob("
+ out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
<< structSize
<< " /* size */);\n";
@@ -517,12 +521,12 @@
out << "public static final void writeVectorToParcel(\n";
out.indent(2);
- out << "HwParcel parcel, ArrayList<"
+ out << "android.os.HwParcel parcel, java.util.ArrayList<"
<< localName()
<< "> _hidl_vec) {\n";
out.unindent();
- out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
+ out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
VectorType::EmitJavaFieldReaderWriterForElementType(
out,
@@ -543,7 +547,7 @@
out << "public final void writeEmbeddedToBlob(\n";
out.indent(2);
- out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
+ out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
out.unindent();
offset = 0;
diff --git a/CompoundType.h b/CompoundType.h
index 340938e..baef137 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -34,6 +34,8 @@
CompoundType(Style style, const char *localName, const Location &location);
+ Style style() const;
+
bool setFields(std::vector<CompoundField *> *fields, std::string *errorMsg);
bool isCompoundType() const override;
diff --git a/GenericBinder.cpp b/GenericBinder.cpp
index 5c5106e..935da31 100644
--- a/GenericBinder.cpp
+++ b/GenericBinder.cpp
@@ -50,7 +50,7 @@
}
std::string GenericBinder::getJavaType(bool /* forInitializer */) const {
- return "IHwBinder";
+ return "android.os.IHwBinder";
}
void GenericBinder::emitReaderWriter(
diff --git a/Interface.cpp b/Interface.cpp
index 317c18c..9f5351c 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -72,19 +72,21 @@
out << "::android::hardware::hidl_vec<::android::hardware::hidl_string> _hidl_return;\n";
out << "_hidl_return.resize(" << chain.size() << ");\n";
for (size_t i = 0; i < chain.size(); ++i) {
- out << "_hidl_return[" << i << "] = \"" << chain[i]->fqName().string() << "\";\n";
+ out << "_hidl_return[" << i << "] = "
+ << chain[i]->fullName()
+ << "::descriptor;\n";
}
out << "_hidl_cb(_hidl_return);\n";
out << "return ::android::hardware::Void();";
},
[this](auto &out) { /* javaImpl */
std::vector<const Interface *> chain = typeChain();
- out << "return new ArrayList<String>(Arrays.asList(\n";
+ out << "return new java.util.ArrayList<String>(java.util.Arrays.asList(\n";
out.indent(); out.indent();
for (size_t i = 0; i < chain.size(); ++i) {
if (i != 0)
out << ",\n";
- out << "\"" << chain[i]->fqName().string() << "\"";
+ out << chain[i]->fullJavaName() << ".kInterfaceName";
}
out << "));";
out.unindent(); out.unindent();
@@ -226,6 +228,14 @@
return fullJavaName();
}
+std::string Interface::getVtsType() const {
+ if (StringHelper::EndsWith(localName(), "Callback")) {
+ return "TYPE_HIDL_CALLBACK";
+ } else {
+ return "TYPE_HIDL_INTERFACE";
+ }
+}
+
void Interface::emitReaderWriter(
Formatter &out,
const std::string &name,
@@ -407,15 +417,16 @@
}
status_t Interface::emitVtsAttributeType(Formatter &out) const {
- out << "type: TYPE_HIDL_CALLBACK\n"
+ out << "type: " << getVtsType() << "\n"
<< "predefined_type: \""
<< localName()
<< "\"\n"
- << "is_callback: true\n";
+ << "is_callback: "
+ << (StringHelper::EndsWith(localName(), "Callback") ? "true" : "false")
+ << "\n";
return OK;
}
-
bool Interface::hasOnewayMethods() const {
for (auto const &method : methods()) {
if (method->isOneway()) {
diff --git a/Interface.h b/Interface.h
index 1c74f6f..f1f10d5 100644
--- a/Interface.h
+++ b/Interface.h
@@ -73,6 +73,7 @@
bool specifyNamespaces) const override;
std::string getJavaType(bool forInitializer) const override;
+ std::string getVtsType() const override;
void emitReaderWriter(
Formatter &out,
diff --git a/VectorType.cpp b/VectorType.cpp
index 5b6caf1..a804b5f 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -73,7 +73,7 @@
elementJavaType = mElementType->getJavaWrapperType();
}
- return "ArrayList<"
+ return "java.util.ArrayList<"
+ elementJavaType
+ ">";
}
@@ -451,7 +451,7 @@
out << "{\n";
out.indent();
- out << "HwBlob _hidl_blob = ";
+ out << "android.os.HwBlob _hidl_blob = ";
if (isReader) {
out << parcelObj
@@ -460,7 +460,7 @@
size_t align, size;
getAlignmentAndSize(&align, &size);
- out << "new HwBlob("
+ out << "new android.os.HwBlob("
<< size
<< " /* size */);\n";
}
@@ -539,7 +539,7 @@
out << "{\n";
out.indent();
- out << "HwBlob childBlob = "
+ out << "android.os.HwBlob childBlob = "
<< parcelName
<< ".readEmbeddedBuffer(\n";
@@ -622,7 +622,7 @@
elementType->getAlignmentAndSize(&elementAlign, &elementSize);
// XXX make HwBlob constructor take a long instead of an int?
- out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
+ out << "android.os.HwBlob childBlob = new android.os.HwBlob((int)(_hidl_vec_size * "
<< elementSize
<< "));\n";
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 36dcad8..c14119a 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -162,11 +162,15 @@
out << "\n";
}
+ if (isInterface) {
+ out << "#include <android/hidl/manager/1.0/IServiceNotification.h>\n\n";
+ }
+
out << "#include <hidl/HidlSupport.h>\n";
- out << "#include <hidl/ServiceManagement.h>\n";
out << "#include <hidl/MQDescriptor.h>\n";
if (isInterface) {
+ out << "#include <hidl/ServiceManagement.h>\n";
out << "#include <hidl/Status.h>\n";
}
@@ -280,9 +284,9 @@
}
}
- out << "\nstatic const ::android::String16 descriptor;\n\n";
+ out << "\nstatic const char* descriptor;\n\n";
- out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n\n";
+ out << "DECLARE_SERVICE_MANAGER_INTERACTIONS(" << baseName << ")\n\n";
out << "private: static int hidlStaticBlock;\n";
}
@@ -752,7 +756,7 @@
<< "::version;\n\n";
// need to be put here, generateStubSource is using this.
- out << "const ::android::String16 I"
+ out << "const char* I"
<< iface->getBaseName()
<< "::descriptor(\""
<< iface->fqName().string()
@@ -762,9 +766,9 @@
<< iface->getBaseName()
<< "::hidlStaticBlock = []() -> int {\n";
out.indentBlock([&] {
- out << "::android::hardware::gBnConstructorMap[::android::String16::std_string(I"
+ out << "::android::hardware::gBnConstructorMap[I"
<< iface->getBaseName()
- << "::descriptor)]\n";
+ << "::descriptor]\n";
out.indentBlock(2, [&] {
out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
out.indentBlock([&] {
@@ -798,7 +802,7 @@
if (err == OK && isInterface) {
const Interface *iface = mRootScope->getInterface();
- out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
+ out << "IMPLEMENT_SERVICE_MANAGER_INTERACTIONS("
<< baseName << ", "
<< "\"" << iface->fqName().package()
<< iface->fqName().atVersion()
@@ -926,12 +930,12 @@
out, method->results(), true /* forResults */);
out << "_hidl_err = _hidl_data.writeInterfaceToken(";
- if (!method->isHidlReserved()) {
- out << superInterface->fqName().cppNamespace()
- << "::IHw"
- << superInterface->getBaseName();
- } else {
+ if (method->isHidlReserved()) {
out << "::android::hardware::IBase";
+ } else {
+ out << superInterface->fqName().cppNamespace()
+ << "::I"
+ << superInterface->getBaseName();
}
out << "::descriptor);\n";
@@ -1220,12 +1224,12 @@
Formatter &out, const Interface *iface, const Method *method) const {
out << "if (!_hidl_data.enforceInterface(";
- if (!method->isHidlReserved()) {
- out << iface->fqName().cppNamespace()
- << "::IHw"
- << iface->getBaseName();
- } else {
+ if (method->isHidlReserved()) {
out << "::android::hardware::IBase";
+ } else {
+ out << iface->fqName().cppNamespace()
+ << "::I"
+ << iface->getBaseName();
}
out << "::descriptor)) {\n";
diff --git a/generateJava.cpp b/generateJava.cpp
index 4fa54d8..b4976a4 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -77,12 +77,6 @@
out << "package " << mPackage.javaPackage() << ";\n\n";
- out << "import android.os.HwBlob;\n";
- out << "import android.os.HwParcel;\n\n";
-
- out << "import java.util.Arrays;\n";
- out << "import java.util.ArrayList;\n\n";
-
for (const auto &item : mImportedNamesForJava) {
out << "import " << item.javaName() << ";\n";
}
@@ -142,15 +136,6 @@
out << "package " << mPackage.javaPackage() << ";\n\n";
- out << "import android.os.IHwBinder;\n";
- out << "import android.os.IHwInterface;\n";
- out << "import android.os.HwBinder;\n";
- out << "import android.os.HwBlob;\n";
- out << "import android.os.HwParcel;\n\n";
-
- out << "import java.util.Arrays;\n";
- out << "import java.util.ArrayList;\n\n";
-
for (const auto &item : mImportedNamesForJava) {
out << "import " << item.javaName() << ";\n";
}
@@ -168,7 +153,7 @@
if (superType != NULL) {
out << superType->fullJavaName();
} else {
- out << "IHwInterface";
+ out << "android.os.IHwInterface";
}
out << " {\n";
@@ -182,7 +167,7 @@
out << "public static "
<< ifaceName
- << " asInterface(IHwBinder binder) {\n";
+ << " asInterface(android.os.IHwBinder binder) {\n";
out.indent();
@@ -192,7 +177,7 @@
out.unindent();
out << "}\n\n";
- out << "IHwInterface iface =\n";
+ out << "android.os.IHwInterface iface =\n";
out.indent();
out.indent();
out << "binder.queryLocalInterface(kInterfaceName);\n\n";
@@ -213,7 +198,7 @@
out.unindent();
out << "}\n\n";
- out << "public IHwBinder asBinder();\n\n";
+ out << "public android.os.IHwBinder asBinder();\n\n";
out << "public static "
<< ifaceName
@@ -223,7 +208,7 @@
out << "return "
<< ifaceName
- << ".asInterface(HwBinder.getService(\""
+ << ".asInterface(android.os.HwBinder.getService(\""
<< iface->fqName().string()
<< "\",serviceName));\n";
@@ -285,14 +270,14 @@
out.indent();
- out << "private IHwBinder mRemote;\n\n";
- out << "public Proxy(IHwBinder remote) {\n";
+ out << "private android.os.IHwBinder mRemote;\n\n";
+ out << "public Proxy(android.os.IHwBinder remote) {\n";
out.indent();
out << "mRemote = remote;\n";
out.unindent();
out << "}\n\n";
- out << "public IHwBinder asBinder() {\n";
+ out << "public android.os.IHwBinder asBinder() {\n";
out.indent();
out << "return mRemote;\n";
out.unindent();
@@ -335,7 +320,7 @@
out << ") {\n";
out.indent();
- out << "HwParcel request = new HwParcel();\n";
+ out << "android.os.HwParcel request = new android.os.HwParcel();\n";
out << "request.writeInterfaceToken("
<< superInterface->fullJavaName()
<< ".kInterfaceName);\n";
@@ -348,7 +333,7 @@
false /* isReader */);
}
- out << "\nHwParcel reply = new HwParcel();\n"
+ out << "\nandroid.os.HwParcel reply = new android.os.HwParcel();\n"
<< "mRemote.transact("
<< method->getSerialId()
<< " /* "
@@ -356,7 +341,7 @@
<< " */, request, reply, ";
if (method->isOneway()) {
- out << "IHwBinder.FLAG_ONEWAY";
+ out << "android.os.IHwBinder.FLAG_ONEWAY";
} else {
out << "0 /* flags */";
}
@@ -411,13 +396,13 @@
////////////////////////////////////////////////////////////////////////////
- out << "\npublic static abstract class Stub extends HwBinder "
+ out << "\npublic static abstract class Stub extends android.os.HwBinder "
<< "implements "
<< ifaceName << " {\n";
out.indent();
- out << "public IHwBinder asBinder() {\n";
+ out << "public android.os.IHwBinder asBinder() {\n";
out.indent();
out << "return this;\n";
out.unindent();
@@ -436,7 +421,7 @@
out << "\n}\n\n";
}
- out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
+ out << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n";
out.indent();
// XXX what about potential superClasses?
out << "if (kInterfaceName.equals(descriptor)) {\n";
@@ -457,7 +442,7 @@
out << "}\n\n";
out << "public void onTransact("
- << "int code, HwParcel request, final HwParcel reply, "
+ << "int code, android.os.HwParcel request, final android.os.HwParcel reply, "
<< "int flags) {\n";
out.indent();
@@ -529,7 +514,7 @@
<< ") {\n";
out.indent();
- out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
+ out << "reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
for (const auto &arg : method->results()) {
emitJavaReaderWriter(
@@ -549,7 +534,7 @@
out << ");\n";
if (!needsCallback) {
- out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
+ out << "reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
if (returnsValue) {
const TypedVar *returnArg = method->results()[0];
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 4e81a49..6ac7e5b 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -33,6 +33,7 @@
#include "hidl-gen_y.h"
#include <android-base/logging.h>
+#include <hidl-util/StringHelper.h>
#include <stdio.h>
using namespace android;
@@ -48,6 +49,119 @@
);
}
+bool isValidInterfaceField(const char *identifier, std::string *errorMsg) {
+ static const std::vector<std::string> reserved({
+ // Injected names to interfaces by auto-generated code
+ "isRemote", "interfaceChain", "descriptor", "hidlStaticBlock", "onTransact",
+ "castFrom", "version", "getInterfaceVersion",
+
+ // Inherited names by interfaces from IInterface / IBinder
+ "onAsBinder", "asBinder", "queryLocalInterface", "getInterfaceDescriptor", "isBinderAlive",
+ "pingBinder", "dump", "transact", "linkToDeath", "unlinkToDeath", "checkSubclass",
+ "attachObject", "findObject", "detachObject", "localBinder", "remoteBinder", "mImpl",
+ });
+ std::string idstr(identifier);
+ if (std::find(reserved.begin(), reserved.end(), idstr) != reserved.end()) {
+ *errorMsg = idstr + " cannot be a name inside an interface";
+ return false;
+ }
+ return true;
+}
+
+bool isValidStructField(const char *identifier, std::string *errorMsg) {
+ static const std::vector<std::string> reserved({
+ // Injected names to structs and unions by auto-generated code
+ "readEmbeddedFromParcel", "writeEmbeddedToParcel", "readVectorFromParcel",
+ "writeVectorToParcel", "writeEmbeddedToBlob",
+ });
+ std::string idstr(identifier);
+ if (std::find(reserved.begin(), reserved.end(), idstr) != reserved.end()) {
+ *errorMsg = idstr + " cannot be a name inside an struct or union";
+ return false;
+ }
+ return true;
+}
+
+bool isValidIdentifier(const char *identifier, std::string *errorMsg) {
+ static const std::vector<std::string> keywords({
+ "uint8_t", "uint16_t", "uint32_t", "uint64_t",
+ "int8_t", "int16_t", "int32_t", "int64_t", "bool", "float", "double",
+ "interface", "struct", "union", "string", "vec", "enum", "ref", "handle",
+ "package", "import", "typedef", "generates", "oneway", "extends",
+ "MQDescriptorSync", "MQDescriptorUnsync",
+ });
+ static const std::vector<std::string> cppKeywords({
+ "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit",
+ "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "case", "catch",
+ "char", "char16_t", "char32_t", "class", "compl", "concept", "const", "constexpr",
+ "const_cast", "continue", "decltype", "default", "delete", "do", "double",
+ "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float",
+ "for", "friend", "goto", "if", "inline", "int", "import", "long", "module", "mutable",
+ "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
+ "private", "protected", "public", "register", "reinterpret_cast", "requires", "return",
+ "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct",
+ "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try",
+ "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
+ "volatile", "wchar_t", "while", "xor", "xor_eq",
+ });
+ static const std::vector<std::string> javaKeywords({
+ "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package",
+ "synchronized", "boolean", "do", "if", "private", "this", "break", "double",
+ "implements", "protected", "throw", "byte", "else", "import", "public", "throws",
+ "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int",
+ "short", "try", "char", "final", "interface", "static", "void", "class", "finally",
+ "long", "strictfp", "volatile", "const", "float", "native", "super", "while",
+ });
+ static const std::vector<std::string> cppCollide({
+ "size_t", "offsetof",
+ "DECLARE_REGISTER_AND_GET_SERVICE", "IMPLEMENT_HWBINDER_META_INTERFACE",
+ "IMPLEMENT_REGISTER_AND_GET_SERVICE"
+ });
+ static const std::vector<std::string> hidlReserved({
+ // Part of HidlSupport
+ "hidl_string", "hidl_vec", "hidl_array", "hidl_version", "toBinder", "castInterface",
+ "make_hidl_version"
+ });
+
+ // errors
+ std::string idstr(identifier);
+ if (std::find(keywords.begin(), keywords.end(), idstr) != keywords.end()) {
+ *errorMsg = idstr + " is a HIDL keyword "
+ "and is therefore not a valid identifier";
+ return false;
+ }
+ if (std::find(cppKeywords.begin(), cppKeywords.end(), idstr) != cppKeywords.end()) {
+ *errorMsg = idstr + " is a C++ keyword "
+ "and is therefore not a valid identifier";
+ return false;
+ }
+ if (std::find(javaKeywords.begin(), javaKeywords.end(), idstr) != javaKeywords.end()) {
+ *errorMsg = idstr + " is a Java keyword "
+ "and is therefore not a valid identifier";
+ return false;
+ }
+ if (std::find(cppCollide.begin(), cppCollide.end(), idstr) != cppCollide.end()) {
+ *errorMsg = idstr + " collides with reserved names in C++ code "
+ "and is therefore not a valid identifier";
+ return false;
+ }
+ if (StringHelper::StartsWith(idstr, "_hidl_")) {
+ *errorMsg = idstr + " starts with _hidl_ "
+ "and is therefore not a valid identifier";
+ return false;
+ }
+ if (StringHelper::EndsWith(idstr, "_cb")) {
+ *errorMsg = idstr + " ends with _cb "
+ "and is therefore not a valid identifier";
+ return false;
+ }
+
+ // warnings
+ if (std::find(hidlReserved.begin(), hidlReserved.end(), idstr) != hidlReserved.end()) {
+ *errorMsg = idstr + " is a name reserved by HIDL and should be avoided";
+ }
+ return true;
+}
%}
@@ -111,12 +225,13 @@
%type<str> package
%type<fqName> fqname
%type<type> fqtype
+%type<str> valid_identifier
%type<type> type opt_storage_type
%type<type> array_type_base
%type<arrayType> array_type
%type<type> opt_extends
-%type<type> type_declaration_body interface_declaration typedef_declaration
+%type<type> type_declaration type_declaration_body interface_declaration typedef_declaration
%type<type> named_struct_or_union_declaration named_enum_declaration
%type<type> compound_declaration annotated_compound_declaration
@@ -164,6 +279,21 @@
%%
+valid_identifier
+ : IDENTIFIER
+ {
+ std::string errorMsg;
+ if (!isValidIdentifier($1, &errorMsg)) {
+ std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n";
+ YYERROR;
+ }
+ if (!errorMsg.empty()) {
+ std::cerr << "WARNING: " << errorMsg << " at " << @1 << "\n";
+ }
+ $$ = $1;
+ }
+ ;
+
opt_annotations
: /* empty */
{
@@ -303,7 +433,7 @@
YYERROR;
}
}
- | IDENTIFIER
+ | valid_identifier
{
$$ = new FQName($1);
if(!$$->isValid()) {
@@ -353,7 +483,7 @@
ast->addSyntaxError();
}
}
- | IMPORT IDENTIFIER require_semicolon
+ | IMPORT valid_identifier require_semicolon
{
if (!ast->addImport($2)) {
std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2
@@ -381,8 +511,27 @@
interface_declarations
: /* empty */
| interface_declarations type_declaration
+ {
+ std::string errorMsg;
+ if ($2 != nullptr &&
+ $2->isNamedType() &&
+ !isValidInterfaceField(static_cast<NamedType *>($2)->localName().c_str(),
+ &errorMsg)) {
+ std::cerr << "ERROR: " << errorMsg << " at "
+ << @2 << "\n";
+ YYERROR;
+ }
+ }
| interface_declarations method_declaration
{
+ std::string errorMsg;
+ if ($2 != nullptr &&
+ !isValidInterfaceField($2->name().c_str(), &errorMsg)) {
+ std::cerr << "ERROR: " << errorMsg << " at "
+ << @2 << "\n";
+ YYERROR;
+ }
+
if ($2 != nullptr) {
if (!ast->scope()->isInterface()) {
std::cerr << "ERROR: unknown error in interface declaration at "
@@ -422,6 +571,7 @@
YYERROR;
}
+ $$ = $2;
}
;
@@ -433,7 +583,7 @@
;
interface_declaration
- : INTERFACE IDENTIFIER opt_extends
+ : INTERFACE valid_identifier opt_extends
{
if ($3 != NULL && !$3->isInterface()) {
std::cerr << "ERROR: You can only extend interfaces. at " << @3
@@ -478,7 +628,7 @@
;
typedef_declaration
- : TYPEDEF type IDENTIFIER
+ : TYPEDEF type valid_identifier
{
std::string errorMsg;
if (!ast->addTypeDef($3, $2, convertYYLoc(@3), &errorMsg)) {
@@ -562,15 +712,15 @@
method_declaration
: error_stmt { $$ = nullptr; }
- | opt_annotations IDENTIFIER '(' typed_vars ')' require_semicolon
+ | opt_annotations valid_identifier '(' typed_vars ')' require_semicolon
{
$$ = new Method($2, $4, new std::vector<TypedVar *>, false, $1);
}
- | opt_annotations ONEWAY IDENTIFIER '(' typed_vars ')' require_semicolon
+ | opt_annotations ONEWAY valid_identifier '(' typed_vars ')' require_semicolon
{
$$ = new Method($3, $5, new std::vector<TypedVar *>, true, $1);
}
- | opt_annotations IDENTIFIER '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon
+ | opt_annotations valid_identifier '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon
{
$$ = new Method($2, $4, $8, false, $1);
}
@@ -593,7 +743,7 @@
}
;
-typed_var : type IDENTIFIER { $$ = new TypedVar($2, $1); }
+typed_var : type valid_identifier { $$ = new TypedVar($2, $1); }
;
@@ -603,7 +753,7 @@
;
named_struct_or_union_declaration
- : struct_or_union_keyword IDENTIFIER
+ : struct_or_union_keyword valid_identifier
{
CompoundType *container = new CompoundType($1, $2, convertYYLoc(@2));
ast->enterScope(container);
@@ -652,8 +802,32 @@
field_declaration
: error_stmt { $$ = nullptr; }
- | type IDENTIFIER require_semicolon { $$ = new CompoundField($2, $1); }
- | annotated_compound_declaration ';' { $$ = NULL; }
+ | type valid_identifier require_semicolon
+ {
+ std::string errorMsg;
+ if (ast->scope()->isCompoundType() &&
+ static_cast<CompoundType *>(ast->scope())->style() == CompoundType::STYLE_STRUCT &&
+ !isValidStructField($2, &errorMsg)) {
+ std::cerr << "ERROR: " << errorMsg << " at "
+ << @2 << "\n";
+ YYERROR;
+ }
+ $$ = new CompoundField($2, $1);
+ }
+ | annotated_compound_declaration ';'
+ {
+ std::string errorMsg;
+ if (ast->scope()->isCompoundType() &&
+ static_cast<CompoundType *>(ast->scope())->style() == CompoundType::STYLE_STRUCT &&
+ $1 != nullptr &&
+ $1->isNamedType() &&
+ !isValidStructField(static_cast<NamedType *>($1)->localName().c_str(), &errorMsg)) {
+ std::cerr << "ERROR: " << errorMsg << " at "
+ << @2 << "\n";
+ YYERROR;
+ }
+ $$ = NULL;
+ }
;
annotated_compound_declaration
@@ -690,7 +864,7 @@
;
named_enum_declaration
- : ENUM IDENTIFIER opt_storage_type
+ : ENUM valid_identifier opt_storage_type
{
ast->enterScope(new EnumType($2, convertYYLoc(@2), $3));
}
@@ -720,8 +894,8 @@
;
enum_value
- : IDENTIFIER { $$ = new EnumValue($1); }
- | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3); }
+ : valid_identifier { $$ = new EnumValue($1); }
+ | valid_identifier '=' const_expr { $$ = new EnumValue($1, $3); }
;
enum_values
diff --git a/test/errors/syntax/1.0/IIdentifier1.hal b/test/errors/syntax/1.0/IIdentifier1.hal
new file mode 100644
index 0000000..9b49c03
--- /dev/null
+++ b/test/errors/syntax/1.0/IIdentifier1.hal
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package tests.errors.syntax@1.0;
+
+// c++ keyword: error
+struct asm {};
+// java keyword: error
+struct transient {};
+// c++ collide: error
+struct offsetof {};
+struct size_t {};
+// hidl names: should warn
+struct hidl_vec{};
+// interface reserved: should be okay
+struct version{};
+
+interface IIdentifier1 {
+ // c++ keyword: error
+ alignof();
+ // java keyword: error
+ native();
+ // c++ collide: error
+ IMPLEMENT_REGISTER_AND_GET_SERVICE();
+ // interface reserved: should error
+ dump();
+ // struct reserved: should be okay
+ readEmbeddedFromParcel();
+};
+
+struct GoodStruct {
+ // java keyword: error
+ int32_t native;
+ // struct reserved: should error
+ int32_t readEmbeddedFromParcel;
+ // interface reserved: should be okay
+ int32_t dump;
+};
diff --git a/test/main.cpp b/test/main.cpp
index 78add39..d59a619 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -2,6 +2,7 @@
#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <android/hardware/tests/foo/1.0/BnFoo.h>
#include <android/hardware/tests/foo/1.0/BnFooCallback.h>
@@ -24,12 +25,11 @@
#error "GTest did not detect pthread library."
#endif
-// TODO(b/32745840)
-#include <utils/String8.h>
-
#include <algorithm>
+#include <condition_variable>
#include <getopt.h>
#include <inttypes.h>
+#include <mutex>
#include <set>
#include <sstream>
#include <vector>
@@ -86,6 +86,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::sp;
using ::android::to_string;
using ::android::Mutex;
@@ -145,6 +146,37 @@
private:
int32_t mCookie;
};
+
+struct ServiceNotification : public IServiceNotification {
+ std::mutex mutex;
+ std::condition_variable condition;
+
+ Return<void> onRegistration(const hidl_string &fqName,
+ const hidl_string &name,
+ bool preexisting) override {
+ if (preexisting) {
+ // not interested in things registered from previous runs of hidl_test
+ return Void();
+ }
+
+ std::unique_lock<std::mutex> lock(mutex);
+
+ mRegistered.push_back(std::string(fqName.c_str()) + "/" + name.c_str());
+
+ lock.unlock();
+ condition.notify_one();
+
+ return Void();
+ }
+
+ const std::vector<std::string> &getRegistrations() const {
+ return mRegistered;
+ }
+
+private:
+ std::vector<std::string> mRegistered{};
+};
+
void signal_handler(int signal)
{
if (signal == SIGTERM) {
@@ -381,7 +413,7 @@
// passthrough TODO(b/32747392)
TEST_F(HidlTest, ServiceListByInterfaceTest) {
if (gMode == BINDERIZED) {
- EXPECT_OK(manager->listByInterface(::android::String8(IParent::descriptor).string(),
+ EXPECT_OK(manager->listByInterface(IParent::descriptor,
[](const hidl_vec<hidl_string> ®istered) {
std::set<std::string> registeredSet;
@@ -411,6 +443,77 @@
}
}
+// passthrough TODO(b/32747392)
+TEST_F(HidlTest, ServiceNotificationTest) {
+ if (gMode == BINDERIZED) {
+ ServiceNotification *notification = new ServiceNotification();
+
+ std::string instanceName = "test-instance";
+ EXPECT_TRUE(ISimple::registerForNotifications(instanceName, notification));
+
+ ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ ProcessState::self()->startThreadPool();
+
+ Simple* instance = new Simple(1);
+ instance->registerAsService(instanceName);
+
+ std::unique_lock<std::mutex> lock(notification->mutex);
+
+ notification->condition.wait_for(
+ lock,
+ std::chrono::milliseconds(2),
+ [¬ification]() {
+ return notification->getRegistrations().size() >= 1;
+ });
+
+ std::vector<std::string> registrations = notification->getRegistrations();
+
+ EXPECT_EQ(registrations.size(), 1u);
+
+ EXPECT_EQ(to_string(registrations.data(), registrations.size()),
+ std::string("['") + Simple::descriptor + "/" + instanceName + "']");
+ }
+}
+
+// passthrough TODO(b/32747392)
+TEST_F(HidlTest, ServiceAllNotificationTest) {
+ if (gMode == BINDERIZED) {
+ ServiceNotification *notification = new ServiceNotification();
+
+ std::string instanceOne = "test-instance-one";
+ std::string instanceTwo = "test-instance-two";
+ EXPECT_TRUE(ISimple::registerForNotifications("", notification));
+
+ ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ ProcessState::self()->startThreadPool();
+
+ Simple* instanceA = new Simple(1);
+ instanceA->registerAsService(instanceOne);
+ Simple* instanceB = new Simple(2);
+ instanceB->registerAsService(instanceTwo);
+
+ std::unique_lock<std::mutex> lock(notification->mutex);
+
+ notification->condition.wait_for(
+ lock,
+ std::chrono::milliseconds(2),
+ [¬ification]() {
+ return notification->getRegistrations().size() >= 2;
+ });
+
+ std::vector<std::string> registrations = notification->getRegistrations();
+ std::sort(registrations.begin(), registrations.end());
+
+ EXPECT_EQ(registrations.size(), 2u);
+
+ std::string descriptor = ISimple::descriptor;
+
+ EXPECT_EQ(to_string(registrations.data(), registrations.size()),
+ "['" + descriptor + "/" + instanceOne + "', '"
+ + descriptor + "/" + instanceTwo + "']");
+ }
+}
+
TEST_F(HidlTest, FooDoThisTest) {
ALOGI("CLIENT call doThis.");
EXPECT_OK(foo->doThis(1.0f));