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> &registered) {
                 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),
+                [&notification]() {
+                   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),
+                [&notification]() {
+                   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));