Merge "struct fields of type "array" should be declared "final"."
diff --git a/AST.cpp b/AST.cpp
index d13167a..d25e4e1 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -21,6 +21,7 @@
 #include "FQName.h"
 #include "HandleType.h"
 #include "Interface.h"
+#include "PredefinedType.h"
 #include "Scope.h"
 #include "TypeDef.h"
 
@@ -311,4 +312,23 @@
     }
 }
 
+bool AST::isJavaCompatible() const {
+    std::string ifaceName;
+    if (!AST::isInterface(&ifaceName)) {
+        for (size_t i = 0; i < mRootScope->countTypes(); ++i) {
+            std::string typeName;
+            const Type *type = mRootScope->typeAt(i, &typeName);
+
+            if (!type->isJavaCompatible()) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    const Interface *iface = mRootScope->getInterface();
+    return iface->isJavaCompatible();
+}
+
 }  // namespace android;
diff --git a/AST.h b/AST.h
index f77a260..6af5604 100644
--- a/AST.h
+++ b/AST.h
@@ -73,13 +73,18 @@
 
     status_t generateCpp(const std::string &outputPath) const;
 
-    status_t generateJava(const std::string &outputPath) const;
-    status_t generateJavaTypes(const std::string &outputPath) const;
+    status_t generateJava(
+            const std::string &outputPath, const char *limitToType) const;
+
+    status_t generateJavaTypes(
+            const std::string &outputPath, const char *limitToType) const;
 
     void getImportedPackages(std::set<FQName> *importSet) const;
 
     status_t generateVts(const std::string &outputPath) const;
 
+    bool isJavaCompatible() const;
+
 private:
     Coordinator *mCoordinator;
     std::string mPath;
@@ -124,6 +129,7 @@
     void enterLeaveNamespace(Formatter &out, bool enter) const;
 
     status_t generateInterfaceHeader(const std::string &outputPath) const;
+    status_t generateHwBinderHeader(const std::string &outputPath) const;
     status_t generateStubHeader(const std::string &outputPath) const;
     status_t generateProxyHeader(const std::string &outputPath) const;
     status_t generateAllSource(const std::string &outputPath) const;
diff --git a/Android.mk b/Android.mk
index 08d6696..ce597f8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -24,6 +24,7 @@
     Interface.cpp               \
     Method.cpp                  \
     NamedType.cpp               \
+    PredefinedType.cpp          \
     ScalarType.cpp              \
     Scope.cpp                   \
     StringType.cpp              \
diff --git a/CompoundType.cpp b/CompoundType.cpp
index a6d5133..74df0a4 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -577,7 +577,17 @@
 }
 
 bool CompoundType::isJavaCompatible() const {
-    return mStyle == STYLE_STRUCT && Scope::isJavaCompatible();
+    if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
+        return false;
+    }
+
+    for (const auto &field : *mFields) {
+        if (!field->type().isJavaCompatible()) {
+            return false;
+        }
+    }
+
+    return true;
 }
 
 void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
diff --git a/ConstantExpression.cpp b/ConstantExpression.cpp
index 0258491..5a5cbf4 100644
--- a/ConstantExpression.cpp
+++ b/ConstantExpression.cpp
@@ -16,33 +16,449 @@
 
 #include "ConstantExpression.h"
 
+#include <stdio.h>
+#include <string>
 #include <utils/String8.h>
+#include <android-base/parseint.h>
+#include <android-base/logging.h>
+#include <sstream>
+
+// The macros are really nasty here. Consider removing
+// as many macros as possible.
+
+#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
+#define OPEQ(__y__) STREQ(op, __y__)
+#define COMPUTE_UNARY(__op__)  if(OPEQ(#__op__)) return __op__ val;
+#define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
+#define OP_IS_BIN_ARITHMETIC  (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
+#define OP_IS_BIN_BITFLIP     (OPEQ("|") || OPEQ("^") || OPEQ("&"))
+#define OP_IS_BIN_COMP        (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
+#define OP_IS_BIN_SHIFT       (OPEQ(">>") || OPEQ("<<"))
+#define OP_IS_BIN_LOGICAL     (OPEQ("||") || OPEQ("&&"))
+#define SK(__x__) ScalarType::Kind::KIND_##__x__
+
+#define SWITCH_KIND(__cond__, __action__, __def__)           \
+    switch(__cond__) {                                        \
+      case SK(BOOL): __action__(bool)                         \
+      case SK(UINT8): __action__(uint8_t)                     \
+      case SK(INT8): __action__(int8_t)                       \
+      case SK(UINT16): __action__(uint16_t)                   \
+      case SK(INT16): __action__(int16_t)                     \
+      case SK(UINT32): __action__(uint32_t)                   \
+      case SK(INT32): __action__(int32_t)                     \
+      case SK(UINT64): __action__(uint64_t)                   \
+      case SK(INT64): __action__(int64_t)                     \
+      default: __def__                                        \
+    }                                                         \
 
 namespace android {
 
-ConstantExpression::ConstantExpression(const char *value)
-    : mValue(value) {
+/* See docs at the end for details on integral promotion. */
+ScalarType::Kind integralPromotion(ScalarType::Kind in) {
+  return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
 }
 
-ConstantExpression::ConstantExpression(const ConstantExpression *lval, const char *op, const ConstantExpression* rval)
-    : mValue(android::String8::format("(%s %s %s)", lval->c_str(), op, rval->c_str()).string()) {
+/* See docs at the end for details on usual arithmetic conversion. */
+ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft, ScalarType::Kind rgt) {
+  CHECK(SK(BOOL) <= lft && lft <= SK(UINT64)
+     && SK(BOOL) <= rgt && rgt <= SK(UINT64)
+     && lft != SK(OPAQUE) && rgt != SK(OPAQUE)
+  );
+  // Kinds in concern: bool, (u)int[8|16|32|64]
+  if(lft == rgt) return lft; // easy case
+  if(lft == SK(BOOL)) return rgt;
+  if(rgt == SK(BOOL)) return lft;
+  bool isLftSigned = (lft == SK(INT8))  || (lft == SK(INT16))
+                  || (lft == SK(INT32)) || (lft == SK(INT64));
+  bool isRgtSigned = (rgt == SK(INT8))  || (rgt == SK(INT16))
+                  || (rgt == SK(INT32)) || (rgt == SK(INT64));
+  if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
+  ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
+  ScalarType::Kind signedRank   = isLftSigned ? lft : rgt;
+  if(unsignedRank >= signedRank) return unsignedRank;
+  if(signedRank > unsignedRank)  return signedRank;
+
+  // Although there is such rule to return "the unsigned counterpart of
+  // the signed operand", it should not reach here in our HIDL grammar.
+  LOG(FATAL) << "Could not do usual arithmetic conversion for type "
+             << lft << "and" << rgt;
+  switch(signedRank) {
+    case SK(INT8):  return SK(UINT8);
+    case SK(INT16): return SK(UINT16);
+    case SK(INT32): return SK(UINT32);
+    case SK(INT64): return SK(UINT64);
+    default: return SK(UINT64);
+  }
 }
+
+template <class T>
+T handleUnary(const char *op, T val) {
+  COMPUTE_UNARY(+)
+  COMPUTE_UNARY(-)
+  COMPUTE_UNARY(!)
+  COMPUTE_UNARY(~)
+  // Should not reach here.
+  LOG(FATAL) << "Could not handleUnary for " << op << " " << val;
+  return static_cast<T>(0xdeadbeef);
+}
+
+template <class T>
+T handleBinaryCommon(T lval, const char *op, T rval) {
+  COMPUTE_BINARY(+)
+  COMPUTE_BINARY(-)
+  COMPUTE_BINARY(*)
+  COMPUTE_BINARY(/)
+  COMPUTE_BINARY(%)
+  COMPUTE_BINARY(|)
+  COMPUTE_BINARY(^)
+  COMPUTE_BINARY(&)
+  // comparison operators: return 0 or 1 by nature.
+  COMPUTE_BINARY(==)
+  COMPUTE_BINARY(!=)
+  COMPUTE_BINARY(<)
+  COMPUTE_BINARY(>)
+  COMPUTE_BINARY(<=)
+  COMPUTE_BINARY(>=)
+  // Should not reach here.
+  LOG(FATAL) << "Could not handleBinaryCommon for "
+             << lval << " " << op << " " << rval;
+  return static_cast<T>(0xdeadbeef);
+}
+
+template <class T>
+T handleShift(T lval, const char *op, int64_t rval) {
+  // just cast rval to int64_t and it should fit.
+  COMPUTE_BINARY(>>)
+  COMPUTE_BINARY(<<)
+  // Should not reach here.
+  LOG(FATAL) << "Could not handleShift for"
+             << lval << " " << op << " " << rval;
+  return static_cast<T>(0xdeadbeef);
+}
+
+bool handleLogical(bool lval, const char *op, bool rval) {
+  COMPUTE_BINARY(||);
+  COMPUTE_BINARY(&&);
+  // Should not reach here.
+  LOG(FATAL) << "Could not handleLogical for"
+             << lval << " " << op << " " << rval;
+  return false;
+}
+
+/* Literals. */
+ConstantExpression::ConstantExpression(const char *value,
+    ConstantExpression::ConstExprType type)
+    : mFormatted(value), mType(type) {
+  if(mType == kConstExprUnknown)
+    return;
+  const char* head = value, *tail = head + strlen(value) - 1;
+  bool isLong = false, isUnsigned = false;
+  bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
+  while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
+    isUnsigned |= *tail == 'u' || *tail == 'U';
+    isLong     |= *tail == 'l' || *tail == 'L';
+    tail--;
+  }
+  char *newVal = strndup(value, tail - head + 1);
+  bool parseOK = base::ParseUint(newVal, &mValue);
+  free(newVal);
+  if(!parseOK) {
+    LOG(FATAL) << "Could not parse as integer: " << value;
+    mType = kConstExprUnknown;
+    return;
+  }
+
+  // guess literal type.
+  if(isLong) {
+    if(isUnsigned) // ul
+      mValueKind = SK(UINT64);
+    else // l
+      mValueKind = SK(INT64);
+  } else { // no l suffix
+    if(isUnsigned) { // u
+      if(mValue <= UINT32_MAX)
+        mValueKind = SK(UINT32);
+      else
+        mValueKind = SK(UINT64);
+    } else { // no suffix
+      if(isHex) {
+        if(mValue <= INT32_MAX) // mValue always >= 0
+          mValueKind = SK(INT32);
+        else if(mValue <= UINT32_MAX)
+          mValueKind = SK(UINT32);
+        else if(mValue <= INT64_MAX) // mValue always >= 0
+          mValueKind = SK(INT64);
+        else if(mValue <= UINT64_MAX)
+          mValueKind = SK(UINT64);
+      } else {
+        if(mValue <= INT32_MAX) // mValue always >= 0
+          mValueKind = SK(INT32);
+        else
+          mValueKind = SK(INT64);
+      }
+    }
+  }
+}
+
+/* Unary operations. */
 ConstantExpression::ConstantExpression(const char *op, const ConstantExpression *value)
-    : mValue(android::String8::format("(%s%s)", op, value->c_str()).string()) {
+    : mFormatted(android::String8::format("(%s%s)", op, value->expr()).string()),
+      mType(kConstExprUnary),
+      mValueKind(value->mValueKind) {
+  if(value->mType == kConstExprUnknown) {
+    mType = kConstExprUnknown;
+    return;
+  }
+#define CASE_UNARY(__type__)\
+            mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
+
+  SWITCH_KIND(mValueKind, CASE_UNARY, mType = kConstExprUnknown; return;)
 }
+
+/* Binary operations. */
+ConstantExpression::ConstantExpression(const ConstantExpression *lval, const char *op, const ConstantExpression* rval)
+    : mFormatted(android::String8::format("(%s %s %s)", lval->expr(), op, rval->expr()).string()),
+      mType(kConstExprBinary)
+{
+  if(lval->mType == kConstExprUnknown || rval->mType == kConstExprUnknown) {
+    mType = kConstExprUnknown;
+    return;
+  }
+
+  bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
+
+  // CASE 1: + - *  / % | ^ & < > <= >= == !=
+  if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
+    // promoted kind for both operands.
+    ScalarType::Kind promoted = usualArithmeticConversion(
+        integralPromotion(lval->mValueKind),
+        integralPromotion(rval->mValueKind));
+    // result kind.
+    mValueKind = isArithmeticOrBitflip
+          ? promoted // arithmetic or bitflip operators generates promoted type
+          : SK(BOOL); // comparison operators generates bool
+
+#define CASE_BINARY_COMMON(__type__)\
+      mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
+
+    SWITCH_KIND(promoted, CASE_BINARY_COMMON, mType = kConstExprUnknown; return;)
+  }
+
+  // CASE 2: << >>
+  if(OP_IS_BIN_SHIFT) {
+    mValueKind = integralPromotion(lval->mValueKind);
+    // instead of promoting rval, simply casting it to int64 should also be good.
+    int64_t numBits = rval->cast<int64_t>();
+    if(numBits < 0) {
+      // shifting with negative number of bits is undefined in C. In HIDL it
+      // is defined as shifting into the other direction.
+      op = OPEQ("<<") ? ">>" : "<<";
+      numBits = -numBits;
+    }
+
+#define CASE_SHIFT(__type__)\
+      mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
+
+    SWITCH_KIND(mValueKind, CASE_SHIFT, mType = kConstExprUnknown; return;)
+  }
+
+  // CASE 3: && ||
+  if(OP_IS_BIN_LOGICAL) {
+    mValueKind = SK(BOOL);
+    // easy; everything is bool.
+    mValue = handleLogical(lval->mValue, op, rval->mValue);
+    return;
+  }
+
+  mType = kConstExprUnknown;
+}
+
+/* Ternary ?: operation. */
 ConstantExpression::ConstantExpression(const ConstantExpression *cond,
                                        const ConstantExpression *trueVal,
                                        const ConstantExpression *falseVal)
-    : mValue(android::String8::format("(%s?%s:%s)",
-             cond->c_str(), trueVal->c_str(), falseVal->c_str()).string()) {
+    : mFormatted(android::String8::format("(%s?%s:%s)",
+             cond->expr(), trueVal->expr(), falseVal->expr()).string()),
+      mType(kConstExprTernary) {
+  // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
+  mValueKind = usualArithmeticConversion(trueVal->mValueKind,
+                                         falseVal->mValueKind);
+
+#define CASE_TERNARY(__type__)\
+    mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
+
+  SWITCH_KIND(mValueKind, CASE_TERNARY, mType = kConstExprUnknown; return;)
 }
 
-const char *ConstantExpression::c_str() const {
-    return mValue.c_str();
+const char *ConstantExpression::expr() const {
+    return mFormatted.c_str();
 }
+
+const char *ConstantExpression::description() const {
+    static const char *const kName[] = {
+      "bool",
+      "void *",
+      "int8_t",
+      "uint8_t",
+      "int16_t",
+      "uint16_t",
+      "int32_t",
+      "uint32_t",
+      "int64_t",
+      "uint64_t",
+      "float",
+      "double"
+  };
+  if(mType == kConstExprUnknown)
+    return expr();
+  std::ostringstream os;
+  os << "(" << kName[mValueKind] << ")" << expr();
+  return strdup(os.str().c_str());
+}
+
 const char *ConstantExpression::value() const {
-    return mValue.c_str();
+  return value0(mValueKind);
 }
 
+const char *ConstantExpression::cppValue(ScalarType::Kind castKind) const {
+  std::string literal(value0(castKind));
+  // this is a hack to translate
+  //       enum x : int64_t {  y = 1l << 63 };
+  // into
+  //       enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
+  // by adding the explicit cast.
+  // Because 9223372036854775808 is uint64_t, and
+  // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
+  // be narrowed to int64_t.
+  if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
+    std::string extra;
+    return strdup(("("
+      + ScalarType(SK(INT64)).getCppType(android::Type::StorageMode_Stack, &extra) // "int64_t"
+      + ")(" + literal + "ull)").c_str());
+  }
+
+  // add suffix if necessary.
+  if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
+  if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
+  return strdup(literal.c_str());
+}
+
+const char *ConstantExpression::javaValue(ScalarType::Kind castKind) const {
+  switch(castKind) {
+    case SK(UINT64): return value0(SK(INT64));
+    case SK(UINT32): return value0(SK(INT32));
+    case SK(UINT16): return value0(SK(INT16));
+    case SK(UINT8) : return value0(SK(INT8));
+    case SK(BOOL)  :
+      if(mType == kConstExprUnknown)
+        return expr();
+      return this->cast<bool>() ? strdup("true") : strdup("false");
+    default: break;
+  }
+  return value0(castKind);
+}
+
+const char *ConstantExpression::value0(ScalarType::Kind castKind) const {
+  if(mType == kConstExprUnknown)
+    return expr();
+
+#define CASE_STR(__type__) return strdup(std::to_string(this->cast<__type__>()).c_str());
+
+  SWITCH_KIND(castKind, CASE_STR, return expr(); );
+}
+
+template<typename T>
+T ConstantExpression::cast() const {
+  CHECK(mType != kConstExprUnknown);
+
+#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
+
+  SWITCH_KIND(mValueKind, CASE_CAST_T, CHECK(false); return 0; );
+}
+
+/*
+
+Evaluating expressions in HIDL language
+
+The following rules are mostly like that in:
+http://en.cppreference.com/w/cpp/language/operator_arithmetic
+http://en.cppreference.com/w/cpp/language/operator_logical
+http://en.cppreference.com/w/cpp/language/operator_comparison
+http://en.cppreference.com/w/cpp/language/operator_other
+
+The type of literal is the first type which the value
+can fit from the list of types depending on the suffix and bases.
+
+suffix              decimal bases           hexadecimal bases
+no suffix           int32_t                 int32_t
+                    int64_t                 uint32_t
+                                            int64_t
+                                            uint64_t
+
+u/U                 uint32_t                (same as left)
+                    uint64_t
+
+l/L                 int64_t                 int64_t
+
+ul/UL/uL/Ul         uint64_t                uint64_t
+
+
+Note: There are no negative integer literals.
+      -1 is the unary minus applied to 1.
+
+Unary arithmetic and bitwise operators (~ + -):
+  don't change the type of the argument.
+  (so -1u = -(1u) has type uint32_t)
+
+Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
+1. Integral promotion is first applied on both sides.
+2. If both operands have the same type, no promotion is necessary.
+3. Usual arithmetic conversions.
+
+Integral promotion: if an operand is of a type with less than 32 bits,
+(including bool), it is promoted to int32_t.
+
+Usual arithmetic conversions:
+1. If operands are both signed or both unsigned, lesser conversion rank is
+   converted to greater conversion rank.
+2. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
+3. Otherwise, if signed's type can hold all values in unsigned's type,
+   -> signed's type
+4. Otherwise, both converted to the unsigned counterpart of the signed operand's
+   type.
+rank: bool < int8_t < int16_t < int32_t < int64_t
+
+
+Shift operators (<< >>):
+1. Integral promotion is applied on both sides.
+2. For unsigned a, a << b discards bits that shifts out.
+   For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
+   For signed negative a, a << b gives error.
+3. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
+   For signed negative a, a >> b discards bits that shifts out, and the signed
+   bit gets extended. ("arithmetic right shift")
+4. Shifting with negative number of bits is undefined. (Currently, the
+   parser will shift into the other direction. This behavior may change.)
+5. Shifting with number of bits exceeding the width of the type is undefined.
+   (Currently, 1 << 32 == 1. This behavior may change.)
+
+Logical operators (!, &&, ||):
+1. Convert first operand to bool. (true if non-zero, false otherwise)
+2. If short-circuited, return the result as type bool, value 1 or 0.
+3. Otherwise, convert second operand to bool, evaluate the result, and return
+   the result in the same fashion.
+
+Arithmetic comparison operators (< > <= >= == !=):
+1. Promote operands in the same way as binary arithmetic and bitwise operators.
+   (Integral promotion + Usual arithmetic conversions)
+2. Return type bool, value 0 or 1 the same way as logical operators.
+
+Ternary conditional operator (?:):
+1. Evaluate the conditional and evaluate the operands.
+2. Return type of expression is the type under usual arithmetic conversions on
+   the second and third operand. (No integral promotions necessary.)
+
+*/
+
 }  // namespace android
 
diff --git a/ConstantExpression.h b/ConstantExpression.h
index 277b9e5..fe2d572 100644
--- a/ConstantExpression.h
+++ b/ConstantExpression.h
@@ -20,16 +20,25 @@
 
 #include <android-base/macros.h>
 #include <string>
+#include "ScalarType.h"
 
 namespace android {
 
-
 /**
  * A constant expression is represented by a tree.
  */
 struct ConstantExpression {
+
+    enum ConstExprType {
+        kConstExprLiteral,
+        kConstExprUnknown,
+        kConstExprUnary,
+        kConstExprBinary,
+        kConstExprTernary
+    };
+
     /* Literals, identifiers */
-    ConstantExpression(const char *value);
+    ConstantExpression(const char *value, ConstExprType type);
     /* binary operations */
     ConstantExpression(const ConstantExpression *value1,
         const char *op, const ConstantExpression* value2);
@@ -41,12 +50,33 @@
                        const ConstantExpression *falseVal);
 
     /* Original expression. */
-    const char *c_str() const;
-    /* Evaluated result. */
+    const char *expr() const;
+    /* Evaluated result in a string form. */
     const char *value() const;
+    /* Evaluated result in a string form, with given contextual kind. */
+    const char *cppValue(ScalarType::Kind castKind) const;
+    /* Evaluated result in a string form, with given contextual kind. */
+    const char *javaValue(ScalarType::Kind castKind) const;
+    /* Original expression with type. */
+    const char *description() const;
 
 private:
-    std::string mValue;
+    /* The formatted expression. */
+    std::string mFormatted;
+    /* The type of the expression. Hints on its original form. */
+    ConstExprType mType;
+    /* The kind of the result value.
+     * Is valid only when mType != kConstExprUnknown. */
+    ScalarType::Kind mValueKind;
+    /* The stored result value.
+     * Is valid only when mType != kConstExprUnknown. */
+    uint64_t mValue;
+    /* Return the value casted to the given type.
+     * First cast it according to mValueKind, then cast it to T.
+     * Assumes mType != kConstExprUnknown */
+    template <typename T> T cast() const;
+    /* Helper function for value(ScalarType::Kind) */
+    const char *value0(ScalarType::Kind castKind) const;
 
     DISALLOW_COPY_AND_ASSIGN(ConstantExpression);
 };
diff --git a/EnumType.cpp b/EnumType.cpp
index bdae930..fbb8a19 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -119,12 +119,19 @@
         for (const auto &entry : type->values()) {
             out << entry->name();
 
-            const char *value = entry->value();
+            const char *value = entry->cppValue(scalarType->getKind());
             if (value != NULL) {
                 out << " = " << value;
             }
 
-            out << ",\n";
+            out << ",";
+
+            const char *comment = entry->comment();
+            if (comment != NULL && strcmp(comment, value) != 0) {
+                out << " // " << comment;
+            }
+
+            out << "\n";
         }
     }
 
@@ -188,7 +195,7 @@
                 << " "
                 << entry->name();
 
-            const char *value = entry->value();
+            const char *value = entry->javaValue(scalarType->getKind());
             if (value != NULL) {
                 out << " = ";
 
@@ -202,7 +209,14 @@
                 }
             }
 
-            out << ";\n";
+            out << ";";
+
+            const char *comment = entry->comment();
+            if (comment != NULL && strcmp(comment, value) != 0) {
+                out << " // " << comment;
+            }
+
+            out << "\n";
         }
     }
 
@@ -240,7 +254,10 @@
 }
 
 status_t EnumType::emitVtsAttributeType(Formatter &out) const {
-    out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
+    out << "type: TYPE_ENUM\n"
+        << "predefined_type: \""
+        << localName()
+        << "\"\n";
     return OK;
 }
 
@@ -265,7 +282,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-EnumValue::EnumValue(const char *name, const char *value)
+EnumValue::EnumValue(const char *name, const ConstantExpression *value)
     : mName(name),
       mValue(value) {
 }
@@ -275,7 +292,18 @@
 }
 
 const char *EnumValue::value() const {
-    return mValue;
+    return mValue ? mValue->value() : nullptr;
+}
+
+const char *EnumValue::cppValue(ScalarType::Kind castKind) const {
+    return mValue ? mValue->cppValue(castKind) : nullptr;
+}
+const char *EnumValue::javaValue(ScalarType::Kind castKind) const {
+    return mValue ? mValue->javaValue(castKind) : nullptr;
+}
+
+const char *EnumValue::comment() const {
+    return mValue ? mValue->description() : nullptr;
 }
 
 }  // namespace android
diff --git a/EnumType.h b/EnumType.h
index fe36bda..ffe0b49 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -18,6 +18,7 @@
 
 #define ENUM_TYPE_H_
 
+#include "ConstantExpression.h"
 #include "NamedType.h"
 
 #include <vector>
@@ -77,14 +78,17 @@
 };
 
 struct EnumValue {
-    EnumValue(const char *name, const char *value = NULL);
+    EnumValue(const char *name, const ConstantExpression *value = nullptr);
 
     std::string name() const;
     const char *value() const;
+    const char *cppValue(ScalarType::Kind castKind) const;
+    const char *javaValue(ScalarType::Kind castKind) const;
+    const char *comment() const;
 
 private:
     std::string mName;
-    const char *mValue;
+    const ConstantExpression *mValue;
 
     DISALLOW_COPY_AND_ASSIGN(EnumValue);
 };
diff --git a/Interface.cpp b/Interface.cpp
index 33e8c88..52d960e 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -56,6 +56,11 @@
     return *mAnnotationsByName;
 }
 
+std::string Interface::getBaseName() const {
+    // cut off the leading 'I'.
+    return localName().substr(1);
+}
+
 std::string Interface::getCppType(StorageMode mode, std::string *extra) const {
     extra->clear();
     const std::string base = "::android::sp<" + fullName() + ">";
@@ -103,7 +108,9 @@
 
         out << name
             << " = "
-            << fullName()
+            << fqName().cppNamespace()
+            << "::IHw"
+            << getBaseName()
             << "::asInterface("
             << binderName
             << ");\n";
@@ -111,14 +118,33 @@
         out.unindent();
         out << "}\n\n";
     } else {
+
+        out << "if (" << name << "->isRemote()) {\n";
+        out.indent();
         out << "_hidl_err = ";
         out << parcelObjDeref
             << "writeStrongBinder("
-            << fullName()
-            << "::asBinder("
-            << name
-            << "));\n";
-
+            << fqName().cppNamespace()
+            << "::IHw"
+            << getBaseName()
+            << "::asBinder(static_cast<"
+            << fqName().cppNamespace()
+            << "::IHw"
+            << getBaseName()
+            << "*>("
+            << name << ".get()"
+            << ")));\n";
+        out.unindent();
+        out << "} else {\n";
+        out.indent();
+        out << "_hidl_err = ";
+        out << parcelObjDeref
+            << "writeStrongBinder("
+            << "new " << fqName().cppNamespace()
+            << "::Bn" << getBaseName() << " "
+            << "(" << name <<"));\n";
+        out.unindent();
+        out << "}\n";
         handleError(out, mode);
     }
 }
@@ -220,7 +246,8 @@
     out << "type: TYPE_HIDL_CALLBACK\n"
         << "predefined_type: \""
         << localName()
-        << "\"\n";
+        << "\"\n"
+        << "is_callback: true\n";
     return OK;
 }
 
@@ -234,6 +261,11 @@
         return true;
     }
 
+    if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
+        mIsJavaCompatibleInProgress = false;
+        return false;
+    }
+
     mIsJavaCompatibleInProgress = true;
 
     if (!Scope::isJavaCompatible()) {
diff --git a/Interface.h b/Interface.h
index 023742c..7d57218 100644
--- a/Interface.h
+++ b/Interface.h
@@ -46,6 +46,8 @@
 
     const AnnotationVector &annotations() const;
 
+    std::string getBaseName() const;
+
     std::string getCppType(StorageMode mode, std::string *extra) const override;
 
     std::string getJavaType() const override;
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/PredefinedType.cpp b/PredefinedType.cpp
new file mode 100644
index 0000000..ea557a4
--- /dev/null
+++ b/PredefinedType.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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 "PredefinedType.h"
+
+#include "Formatter.h"
+
+#include <android-base/logging.h>
+
+namespace android {
+
+PredefinedType::PredefinedType(const char *name)
+    : mName(name) {
+}
+
+std::string PredefinedType::getCppType(
+        StorageMode mode, std::string *extra) const {
+    extra->clear();
+
+    const std::string base = mName;
+
+    switch (mode) {
+        case StorageMode_Stack:
+            return base;
+
+        case StorageMode_Argument:
+            return "const " + base + "&";
+
+        case StorageMode_Result:
+            return "const " + base + "*";
+    }
+}
+
+std::string PredefinedType::getJavaType() const {
+    CHECK(!"Should not be here");
+    return std::string();
+}
+
+void PredefinedType::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 "
+            << mName
+            << " *)"
+            << 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,
+            name,
+            isReader /* nameIsPointer */,
+            parcelObj,
+            parcelObjIsPointer,
+            isReader,
+            mode,
+            parentName,
+            "0 /* parentOffset */");
+}
+
+void PredefinedType::emitReaderWriterEmbedded(
+        Formatter &out,
+        const std::string &name,
+        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,
+            mName,
+            "" /* childName */);
+}
+
+bool PredefinedType::isJavaCompatible() const {
+    return false;
+}
+
+bool PredefinedType::needsEmbeddedReadWrite() const {
+    return true;
+}
+
+bool PredefinedType::resultNeedsDeref() const {
+    return true;
+}
+
+}  // namespace android
+
diff --git a/PredefinedType.h b/PredefinedType.h
new file mode 100644
index 0000000..5915eb3
--- /dev/null
+++ b/PredefinedType.h
@@ -0,0 +1,63 @@
+/*
+ * 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 PREDEFINED_TYPE_H_
+
+#define PREDEFINED_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct PredefinedType : public Type {
+    PredefinedType(const char *name);
+
+    std::string getCppType(StorageMode mode, std::string *extra) const override;
+    std::string getJavaType() 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,
+            const std::string &name,
+            bool nameIsPointer,
+            const std::string &parcelObj,
+            bool parcelObjIsPointer,
+            bool isReader,
+            ErrorMode mode,
+            const std::string &parentName,
+            const std::string &offsetText) const override;
+
+    bool isJavaCompatible() const override;
+
+    bool needsEmbeddedReadWrite() const override;
+    bool resultNeedsDeref() const override;
+
+private:
+    std::string mName;
+
+    DISALLOW_COPY_AND_ASSIGN(PredefinedType);
+};
+
+}  // namespace android
+
+#endif  // PREDEFINED_TYPE_H_
diff --git a/ScalarType.cpp b/ScalarType.cpp
index cff91c3..f751ae6 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -208,11 +208,21 @@
 }
 
 status_t ScalarType::emitVtsTypeDeclarations(Formatter &out) const {
-    std::string extra;
-    out << "type: TYPE_SCALAR\n"
-        << "scalar_type: "
-        << getCppType(StorageMode_Stack, &extra)
-        << "\n";
+    static const char *const kName[] = {
+            "bool_t",
+            "opaque",
+            "int8_t",
+            "uint8_t",
+            "int16_t",
+            "uint16_t",
+            "int32_t",
+            "uint32_t",
+            "int64_t",
+            "uint64_t",
+            "float_t",
+            "double_t"
+    };
+    out << "type: TYPE_SCALAR\n"<< "scalar_type: \""<< kName[mKind]<< "\"\n";
     return OK;
 }
 
@@ -235,5 +245,9 @@
     *align = *size = kAlign[mKind];
 }
 
+ScalarType::Kind ScalarType::getKind() const {
+    return mKind;
+}
+
 }  // namespace android
 
diff --git a/ScalarType.h b/ScalarType.h
index fd9fb67..06892bf 100644
--- a/ScalarType.h
+++ b/ScalarType.h
@@ -78,6 +78,8 @@
 
     void getAlignmentAndSize(size_t *align, size_t *size) const override;
 
+    Kind getKind() const;
+
 private:
     Kind mKind;
 
diff --git a/c2hal/AST.cpp b/c2hal/AST.cpp
new file mode 100644
index 0000000..f803cc1
--- /dev/null
+++ b/c2hal/AST.cpp
@@ -0,0 +1,339 @@
+/*
+ * 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 "AST.h"
+
+#include "FunctionDeclaration.h"
+#include "EnumVarDeclaration.h"
+#include "Scope.h"
+#include "Declaration.h"
+#include "CompositeDeclaration.h"
+#include "Define.h"
+#include "Include.h"
+
+#include <string>
+#include <algorithm>
+#include <stdlib.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+
+namespace android {
+
+AST::AST(const std::string &path,
+         const std::string &outputDir,
+         const std::string &package,
+         bool isOpenGl)
+    : mScanner(NULL),
+      mPath(path),
+      mOutputDir(outputDir),
+      mPackage(package),
+      mIsOpenGl(isOpenGl)
+    {}
+
+AST::~AST() {
+    delete mExpression;
+
+    if(mDeclarations != NULL) {
+        for(auto* decl : *mDeclarations) {
+            delete decl;
+        }
+    }
+    delete mDeclarations;
+
+    if(mInterfaces != NULL) {
+        for(auto* inter : *mInterfaces) {
+            delete inter;
+        }
+    }
+    delete mInterfaces;
+
+    if(mIncludes != NULL) {
+        for(auto* incl : *mIncludes) {
+            delete incl;
+        }
+    }
+    delete mIncludes;
+}
+
+void *AST::scanner() {
+    return mScanner;
+}
+
+void AST::setScanner(void *scanner) {
+    mScanner = scanner;
+}
+
+bool AST::isOpenGl() const {
+    return mIsOpenGl;
+}
+
+const std::string& AST::getFilename() const {
+    return mPath;
+}
+
+void AST::setDeclarations(std::vector<Declaration *> *declarations) {
+    mDeclarations = declarations;
+}
+
+void AST::setIncludes(std::vector<Include *> *includes) {
+    mIncludes = includes;
+}
+
+Expression *AST::getExpression() const {
+    return mExpression;
+}
+void AST::setExpression(Expression *expression) {
+    mExpression = expression;
+}
+
+const Scope<Define *> &AST::getDefinesScope() const {
+    return mDefinesScope;
+}
+
+Scope<Define *> &AST::getDefinesScope() {
+    return mDefinesScope;
+}
+
+void AST::processContents() {
+    CHECK(mDeclarations != NULL);
+
+    for (auto &declaration : *mDeclarations) {
+        CHECK(declaration != NULL);
+
+        declaration->processContents(*this);
+    }
+
+    isolateInterfaces();
+    isolateGlobalInterface();
+    isolateIncludes();
+
+    isolateConstants(Expression::Type::U64);
+    isolateConstants(Expression::Type::S64);
+    isolateConstants(Expression::Type::U32);
+    isolateConstants(Expression::Type::S32);
+}
+
+/* take interface-like structs out of the type file */
+void AST::isolateInterfaces() {
+    mInterfaces = new std::vector<CompositeDeclaration*>;
+
+    auto it = mDeclarations->begin();
+    while (it != mDeclarations->end()) {
+        if ((*it)->decType() == CompositeDeclaration::type()
+            && ((CompositeDeclaration *) (*it))->isInterface()) {
+
+            mInterfaces->push_back((CompositeDeclaration *) *it);
+            it = mDeclarations->erase(it);
+        } else {
+            it++;
+        }
+    }
+}
+
+/* take global function declarations out of the type file and into a new
+ * interface
+ */
+void AST::isolateGlobalInterface() {
+    auto globalFuns = new std::vector<Declaration*>;
+
+    auto it = mDeclarations->begin();
+    while (it != mDeclarations->end()) {
+        if ((*it)->decType() == FunctionDeclaration::type()) {
+
+            globalFuns->push_back(*it);
+            it = mDeclarations->erase(it);
+        } else {
+            it++;
+        }
+    }
+
+    if (!globalFuns->empty()) {
+        std::string path = mPackage.substr(0, mPackage.find_first_of('@'));
+        std::string name = path.substr(path.find_last_of('.') + 1);
+
+        auto interface = new CompositeDeclaration(
+            Type::Qualifier::STRUCT,
+            name + "_global_t",
+            globalFuns);
+
+        mInterfaces->push_back(interface);
+    }
+}
+
+void AST::isolateIncludes() {
+    mIncludes = new std::vector<Include*>;
+
+    auto it = mDeclarations->begin();
+    while (it != mDeclarations->end()) {
+        if ((*it)->decType() == Include::type()) {
+
+            mIncludes->push_back((Include *) *it);
+            it = mDeclarations->erase(it);
+        } else {
+            it++;
+        }
+    }
+}
+
+void AST::isolateConstants(Expression::Type ofType) {
+    auto constants = new std::vector<Declaration*>;
+
+    auto it = mDeclarations->begin();
+    while (it != mDeclarations->end()) {
+        if ((*it)->decType() == Define::type() &&
+            ((Define *)*it)->getExpressionType() == ofType) {
+
+            Define* define = (Define *)*it;
+
+            auto var = new EnumVarDeclaration(define->getName(),
+                                              define->getExpression());
+
+            define->setExpression(NULL);
+
+            constants->push_back(var);
+            it = mDeclarations->erase(it);
+
+            delete define;
+        } else {
+            it++;
+        }
+    }
+
+    if (!constants->empty()) {
+        auto constEnum = new CompositeDeclaration(
+            Type::Qualifier::ENUM,
+            "Const" + Expression::getTypeDescription(ofType),
+            constants);
+
+        constEnum->setEnumTypeName(Expression::getTypeName(ofType));
+
+        mDeclarations->insert(mDeclarations->begin(), constEnum);
+    }
+}
+
+status_t AST::generateCode() const {
+    CHECK(mDeclarations != NULL);
+
+    status_t err;
+
+    for (auto &interface : *mInterfaces) {
+        err = generateFile(interface);
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    err = generateTypesFile();
+
+    if (err != OK) {
+        return err;
+    }
+
+    return OK;
+}
+
+status_t AST::generateFile(CompositeDeclaration* declaration) const {
+    std::string fileName = declaration->getInterfaceName() + ".hal";
+
+    FILE *file = fopen((getFileDir() + fileName).c_str(), "w");
+
+    if(file == NULL) {
+        return -errno;
+    }
+
+    Formatter out(file); // formatter closes out
+
+    generatePackageLine(out);
+    generateIncludes(out);
+
+    declaration->generateInterface(out);
+
+    return OK;
+}
+
+status_t AST::generateTypesFile() const {
+    if (mDeclarations->empty()) {
+        return OK;
+    }
+
+    FILE *file = fopen((getFileDir() + "types.hal").c_str(), "w");
+
+    if(file == NULL) {
+        return -errno;
+    }
+
+    Formatter out(file); // formatter closes out
+
+    generatePackageLine(out);
+    generateIncludes(out);
+
+    for (auto &declaration : *mDeclarations) {
+        declaration->generateCommentText(out);
+        declaration->generateSource(out);
+        out << "\n";
+    }
+
+    return OK;
+}
+
+void AST::generateIncludes(Formatter &out) const {
+    for (auto &include : *mIncludes) {
+        include->generateSource(out);
+        out << "\n";
+    }
+}
+
+void AST::generatePackageLine(Formatter &out) const {
+    out << "package "
+        << mPackage
+        << ";\n\n";
+}
+
+bool MakeParentHierarchy(const std::string &path) {
+    static const mode_t kMode = 0755;
+
+    size_t start = 1;  // Ignore leading '/'
+    size_t slashPos;
+    while ((slashPos = path.find("/", start)) != std::string::npos) {
+        std::string partial = path.substr(0, slashPos);
+
+        struct stat st;
+        if (stat(partial.c_str(), &st) < 0) {
+            if (errno != ENOENT) {
+                return false;
+            }
+
+            int res = mkdir(partial.c_str(), kMode);
+            if (res < 0) {
+                return false;
+            }
+        } else if (!S_ISDIR(st.st_mode)) {
+            return false;
+        }
+
+        start = slashPos + 1;
+    }
+
+    return true;
+}
+
+const std::string AST::getFileDir() const {
+    CHECK(MakeParentHierarchy(mOutputDir));
+    return mOutputDir;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/c2hal/AST.h b/c2hal/AST.h
new file mode 100644
index 0000000..bc0808a
--- /dev/null
+++ b/c2hal/AST.h
@@ -0,0 +1,98 @@
+/*
+ * 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 AST_H_
+#define AST_H_
+
+#include "../Formatter.h"
+#include "Scope.h"
+#include "Expression.h"
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include <utils/Errors.h>
+
+namespace android {
+
+struct Include;
+struct Define;
+struct CompositeDeclaration;
+struct Declaration;
+
+struct AST {
+    AST(const std::string &path,
+        const std::string &outputDir,
+        const std::string &package,
+        bool isOpenGl);
+    ~AST();
+
+    void *scanner();
+    void setScanner(void *scanner);
+
+    bool isOpenGl() const;
+
+    const std::string &getFilename() const;
+
+    void setDeclarations(std::vector<Declaration *> *declarations);
+    void setIncludes(std::vector<Include *> *includes);
+
+    Expression *getExpression() const;
+    void setExpression(Expression *expression);
+
+    status_t generateCode() const;
+
+    void processContents();
+
+    const Scope<Define *> &getDefinesScope() const;
+    Scope<Define *> &getDefinesScope();
+
+private:
+    void * mScanner = NULL;
+    std::string mPath;
+    std::string mOutputDir;
+    std::string mPackage;
+
+    bool mIsOpenGl;
+
+    Expression* mExpression = NULL;
+
+    std::vector<Declaration *> *mDeclarations = NULL;
+    std::vector<CompositeDeclaration *> *mInterfaces = NULL;
+    std::vector<Include *> *mIncludes = NULL;
+
+    Scope<Define *> mDefinesScope;
+
+    const std::string getFileDir() const;
+
+    status_t generateFile(CompositeDeclaration* declaration) const;
+    status_t generateTypesFile() const;
+
+    void generateIncludes(Formatter &out) const;
+    void generatePackageLine(Formatter &out) const;
+
+    void isolateInterfaces();
+    void isolateGlobalInterface();
+    void isolateIncludes();
+    void isolateConstants(Expression::Type ofType);
+
+    DISALLOW_COPY_AND_ASSIGN(AST);
+};
+
+}  // namespace android
+
+#endif  // AST_H_
diff --git a/c2hal/Android.mk b/c2hal/Android.mk
new file mode 100644
index 0000000..828264b
--- /dev/null
+++ b/c2hal/Android.mk
@@ -0,0 +1,35 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := c2hal
+LOCAL_MODULE_CLASS := EXECUTABLES
+# LOCAL_IS_HOST_MODULE := true
+
+LOCAL_SRC_FILES :=              \
+    ../Formatter.cpp            \
+    AST.cpp                     \
+    c2hal_l.ll                  \
+    c2hal_y.yy                  \
+    CompositeDeclaration.cpp    \
+    Declaration.cpp             \
+    Define.cpp                  \
+    EnumVarDeclaration.cpp      \
+    Expression.cpp              \
+    FunctionDeclaration.cpp     \
+    Include.cpp                 \
+    main.cpp                    \
+    Note.cpp                    \
+    Type.cpp                    \
+    TypeDef.cpp                 \
+    VarDeclaration.cpp          \
+
+LOCAL_SHARED_LIBRARIES :=       \
+    libbase                     \
+    liblog                      \
+
+LOCAL_STATIC_LIBRARIES :=       \
+    libutils                    \
+
+LOCAL_CFLAGS := -O0 -g
+
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/c2hal/CompositeDeclaration.cpp b/c2hal/CompositeDeclaration.cpp
new file mode 100644
index 0000000..135654c
--- /dev/null
+++ b/c2hal/CompositeDeclaration.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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 "CompositeDeclaration.h"
+#include "FunctionDeclaration.h"
+#include "Declaration.h"
+
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <sstream>
+
+namespace android {
+
+static std::string capitalize(const std::string in) {
+    std::string out{in};
+
+    if(!out.empty()) {
+        out[0] = toupper(out[0]);
+    }
+
+    return out;
+}
+
+static std::string snakeCaseToCamelCase(const std::string in) {
+    std::istringstream ss(in);
+    std::string word;
+    std::string out;
+
+    while (std::getline(ss, word, '_')) {
+        out += capitalize(word);
+    }
+
+    return out;
+}
+
+CompositeDeclaration::CompositeDeclaration(
+        const Type::Qualifier::Qualification qualifier,
+        const std::string &name,
+        std::vector<android::Declaration *> *fieldDeclarations)
+    : Declaration(name), mQualifier(qualifier), mFieldDeclarations(fieldDeclarations)
+    {}
+
+CompositeDeclaration::~CompositeDeclaration() {
+    if(mFieldDeclarations != NULL) {
+        for(auto* decl : *mFieldDeclarations) {
+            delete decl;
+        }
+    }
+    delete mFieldDeclarations;
+}
+
+
+const Type::Qualifier::Qualification &CompositeDeclaration::getQualifier() const {
+    return mQualifier;
+}
+const std::vector<android::Declaration *>*
+    CompositeDeclaration::getFieldDeclarations() const {
+    return mFieldDeclarations;
+}
+
+void CompositeDeclaration::generateInterface(Formatter &out) const {
+    generateCommentText(out);
+    out << "interface " << getInterfaceName() << " {\n\n";
+
+    generateBody(out);
+
+    out << "};\n";
+}
+
+void CompositeDeclaration::generateSource(Formatter &out) const {
+    CHECK(mQualifier == Type::Qualifier::STRUCT ||
+          mQualifier == Type::Qualifier::UNION ||
+          mQualifier == Type::Qualifier::ENUM);
+
+    out << Type::qualifierText(mQualifier) << " " << getName();
+
+    if (mQualifier == Type::Qualifier::ENUM) {
+        out << " : ";
+
+        if (mEnumTypeName.empty()) {
+            out << "int32_t /* NOTE: type is guessed */";
+        } else {
+            out << mEnumTypeName;
+        }
+
+    }
+
+    out << " {\n";
+
+    generateBody(out);
+
+    out << "};\n";
+}
+
+void CompositeDeclaration::generateBody(Formatter &out) const {
+    out.indent();
+
+    for (auto *declaration : *mFieldDeclarations) {
+        declaration->generateCommentText(out);
+        declaration->generateSource(out);
+        out << "\n";
+    }
+
+    out.unindent();
+}
+
+void CompositeDeclaration::processContents(AST &ast) {
+    for (auto &declaration : *mFieldDeclarations) {
+        declaration->processContents(ast);
+    }
+
+    if (isInterface()) {
+        // move non function fields into a containing struct
+
+        auto nonFpDecs = new std::vector<Declaration*>;
+
+        auto it = mFieldDeclarations->begin();
+        while (it != mFieldDeclarations->end()) {
+            if((*it)->decType() != FunctionDeclaration::type()) {
+                nonFpDecs->push_back(*it);
+                it = mFieldDeclarations->erase(it);
+            } else {
+                it++;
+            }
+        }
+
+        if (!nonFpDecs->empty()) {
+            auto subStruct = new CompositeDeclaration(Type::Qualifier::STRUCT,
+                                                      getName(),
+                                                      nonFpDecs);
+
+            mFieldDeclarations->insert(mFieldDeclarations->begin(), subStruct);
+        }
+    }
+}
+
+std::string CompositeDeclaration::getInterfaceName() const {
+    std::string baseName{getName()};
+
+    if (baseName.length() > 2 &&
+        baseName.substr(baseName.length() - 2) == "_t") {
+
+        baseName = baseName.substr(0, baseName.length() - 2);
+    }
+
+    return "I" + snakeCaseToCamelCase(baseName);
+}
+
+bool CompositeDeclaration::isInterface() const {
+    if (mQualifier != Type::Qualifier::STRUCT) {
+        return false;
+    }
+
+    for (auto &declaration : *mFieldDeclarations) {
+        if (declaration->decType() == FunctionDeclaration::type()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void CompositeDeclaration::setEnumTypeName(const std::string &name) {
+    CHECK(mQualifier == Type::Qualifier::ENUM);
+
+    mEnumTypeName = name;
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/CompositeDeclaration.h b/c2hal/CompositeDeclaration.h
new file mode 100644
index 0000000..a449216
--- /dev/null
+++ b/c2hal/CompositeDeclaration.h
@@ -0,0 +1,60 @@
+/*
+ * 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 COMPOSITE_DECLARATION_H_
+#define COMPOSITE_DECLARATION_H_
+
+#include "Declaration.h"
+#include "Type.h"
+
+namespace android {
+
+struct CompositeDeclaration : Declaration {
+    CompositeDeclaration(
+        const Type::Qualifier::Qualification qualifier,
+        const std::string &name,
+        std::vector<android::Declaration *> *fieldDeclarations);
+    ~CompositeDeclaration();
+
+    const Type::Qualifier::Qualification &getQualifier() const;
+    const std::vector<android::Declaration *>* getFieldDeclarations() const;
+
+    static std::string type() { return "composite"; }
+    const std::string decType() const override { return type(); }
+
+    void generateSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+    void generateInterface(Formatter &out) const;
+    std::string getInterfaceName() const;
+    bool isInterface() const;
+
+    void setEnumTypeName(const std::string &name);
+
+private:
+    const Type::Qualifier::Qualification mQualifier;
+    std::vector<android::Declaration *> *mFieldDeclarations;
+
+    std::string mEnumTypeName;
+
+    void generateBody(Formatter &out) const;
+
+    DISALLOW_COPY_AND_ASSIGN(CompositeDeclaration);
+};
+
+}  // namespace android
+
+#endif  // COMPOSITE_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Declaration.cpp b/c2hal/Declaration.cpp
new file mode 100644
index 0000000..8f88ea6
--- /dev/null
+++ b/c2hal/Declaration.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 "Declaration.h"
+
+#include <regex>
+
+namespace android {
+
+static const std::regex RE_LEADING_SPACES("\n +");
+
+Declaration::Declaration(const std::string &name)
+    : mName(name)
+    {}
+
+Declaration::~Declaration() {}
+
+const std::string& Declaration::getName() const {
+    return mName;
+}
+void Declaration::setName(const std::string &name) {
+    mName = name;
+}
+
+const std::string& Declaration::getComment() const {
+    return mComment;
+}
+void Declaration::setComment(const std::string &comment) {
+    // remove excess leading whitespace
+    mComment = regex_replace(comment, RE_LEADING_SPACES, "\n ");
+}
+
+void Declaration::generateCommentText(Formatter &out) const {
+    if (!mComment.empty()) {
+        out << mComment << "\n";
+    }
+}
+
+void Declaration::generateParameterSource(Formatter &out) const {
+    out << "/* UNKOWN PARAMTER */" << "\n";
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Declaration.h b/c2hal/Declaration.h
new file mode 100644
index 0000000..bd7bce0
--- /dev/null
+++ b/c2hal/Declaration.h
@@ -0,0 +1,63 @@
+/*
+ * 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 DECLARATION_H_
+#define DECLARATION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "../Formatter.h"
+
+namespace android {
+
+struct AST;
+
+struct Declaration {
+    Declaration(const std::string &name);
+    virtual ~Declaration();
+
+    const std::string &getName() const;
+    void setName(const std::string &name);
+
+    const std::string& getComment() const;
+    void setComment(const std::string &comment);
+
+    std::string getInterfaceName() const;
+
+    void generateCommentText(Formatter &out) const;
+
+    virtual const std::string decType() const = 0;
+
+    /* for example "int test;" */
+    virtual void generateSource(Formatter &out) const = 0;
+
+    /* for example "int test" in fun(int test, float jeff) */
+    virtual void generateParameterSource(Formatter &out) const;
+
+    virtual void processContents(AST &ast) = 0;
+
+private:
+    std::string mName;
+    std::string mComment;
+
+    DISALLOW_COPY_AND_ASSIGN(Declaration);
+};
+
+}  // namespace android
+
+#endif  // DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Define.cpp b/c2hal/Define.cpp
new file mode 100644
index 0000000..02afded
--- /dev/null
+++ b/c2hal/Define.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "Define.h"
+
+#include "AST.h"
+
+extern android::status_t parseExpression(android::AST *ast, std::string str);
+
+namespace android {
+
+Define::Define(const std::string &name, const std::string &slurp)
+    : Declaration(name), mSlurp(slurp)
+    {}
+
+Define::~Define() {
+    delete mExpression;
+}
+
+Expression::Type Define::getExpressionType() const {
+    return mExpressionType;
+}
+Expression *Define::getExpression() const {
+    return mExpression;
+}
+void Define::setExpression(Expression* expression) {
+    mExpression = expression;
+}
+
+void Define::generateSource(Formatter &out) const {
+    out << "/* #define " << getName() << " " << mSlurp << " */\n";
+}
+
+void Define::processContents(AST &ast) {
+    status_t res = parseExpression(&ast, mSlurp);
+
+    if (res != 0) {
+        mExpressionType = Expression::Type::UNKOWN;
+        return;
+    }
+
+    mExpression = ast.getExpression();
+    ast.setExpression(NULL);
+
+    mExpressionType = mExpression->getType(ast);
+
+    ast.getDefinesScope().enter(getName(), this);
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Define.h b/c2hal/Define.h
new file mode 100644
index 0000000..e66159d
--- /dev/null
+++ b/c2hal/Define.h
@@ -0,0 +1,54 @@
+/*
+ * 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 DEFINE_H_
+#define DEFINE_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+#include "Expression.h"
+
+namespace android {
+
+struct Define : Declaration {
+    Define(const std::string &name, const std::string &slurp);
+    ~Define();
+
+    static std::string type() { return "define"; }
+    const std::string decType() const override { return type(); }
+
+    void generateSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+    Expression::Type getExpressionType() const;
+    Expression *getExpression() const;
+    void setExpression(Expression* expression);
+
+private:
+    const std::string mSlurp;
+
+    Expression::Type mExpressionType;
+    Expression* mExpression = NULL;
+
+    DISALLOW_COPY_AND_ASSIGN(Define);
+};
+
+}  // namespace android
+
+#endif  // DEFINE_H_
\ No newline at end of file
diff --git a/c2hal/EnumVarDeclaration.cpp b/c2hal/EnumVarDeclaration.cpp
new file mode 100644
index 0000000..f7c4671
--- /dev/null
+++ b/c2hal/EnumVarDeclaration.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "EnumVarDeclaration.h"
+#include "Expression.h"
+
+namespace android {
+
+EnumVarDeclaration::EnumVarDeclaration(const std::string &name, Expression *expression)
+    : Declaration(name), mExpression(expression)
+    {}
+
+EnumVarDeclaration::~EnumVarDeclaration() {
+    delete mExpression;
+}
+
+Expression *EnumVarDeclaration::getExpression() const {
+    return mExpression;
+}
+
+void EnumVarDeclaration::generateSource(Formatter &out) const {
+    out << getName();
+
+    if(mExpression != NULL) {
+        out << " = " << mExpression->toString();
+    }
+
+    out << ",\n";
+}
+
+void EnumVarDeclaration::processContents(AST &) {
+    // nothing to do
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/EnumVarDeclaration.h b/c2hal/EnumVarDeclaration.h
new file mode 100644
index 0000000..10978e0
--- /dev/null
+++ b/c2hal/EnumVarDeclaration.h
@@ -0,0 +1,50 @@
+/*
+ * 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 ENUM_VAR_DECLARATION_H_
+#define ENUM_VAR_DECLARATION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+
+namespace android {
+
+struct Expression;
+
+struct EnumVarDeclaration : Declaration {
+    EnumVarDeclaration(const std::string &name, Expression *expression);
+    ~EnumVarDeclaration();
+
+    static std::string type() { return "enum"; }
+    const std::string decType() const override { return type(); }
+
+    Expression *getExpression() const;
+
+    void generateSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+private:
+    Expression *mExpression = NULL;
+
+    DISALLOW_COPY_AND_ASSIGN(EnumVarDeclaration);
+};
+
+}  // namespace android
+
+#endif  // ENUM_VAR_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Expression.cpp b/c2hal/Expression.cpp
new file mode 100644
index 0000000..f9c8bb2
--- /dev/null
+++ b/c2hal/Expression.cpp
@@ -0,0 +1,299 @@
+/*
+ * 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 "Expression.h"
+#include "Define.h"
+#include "AST.h"
+#include "Scope.h"
+
+#include <vector>
+#include <regex>
+
+namespace android {
+
+static const std::regex RE_S32("[^ul]$");
+static const std::regex RE_U32("[^ul]u$");
+static const std::regex RE_S64("[^ul](l|ll)$");
+static const std::regex RE_U64("[^ul](ul|ull)$");
+
+// static
+Expression::Type Expression::integralType(std::string integer) {
+    if (std::regex_search(integer, RE_S32)) {
+        return Type::S32;
+    }
+
+    if (std::regex_search(integer, RE_U32)) {
+        return Type::U32;
+    }
+
+    if (std::regex_search(integer, RE_S64)) {
+        return Type::S64;
+    }
+
+    if (std::regex_search(integer, RE_U64)) {
+        return Type::U64;
+    }
+
+    LOG(WARNING) << "UNKOWN INTEGER LITERAL: " << integer;
+
+    return Type::UNKOWN;
+}
+
+// static
+Expression::Type Expression::coalesceTypes(Type lhs, Type rhs) {
+    // because we are reducing everything to two ranks, we can heavily simplify
+    // conversion rules
+
+#define SIGNED(i) (i & 2) // i & 0b10
+#define MAX_RANK(i) (i | 1) // i | 0b01
+
+    if (lhs == rhs) {
+        return lhs;
+    }
+
+    // lhs != rhs
+    if (SIGNED(lhs) == SIGNED(rhs)) {
+        return (Type)MAX_RANK(lhs);
+    }
+
+    // lhs != rhs && SIGNED(lhs) != SIGNED(rhs)
+    if (lhs == U32 || rhs == U32) {
+        return S64;
+    }
+
+    return Type::UNKOWN;
+
+#undef SIGNED
+#undef MAX_RANK
+
+}
+
+struct ParenthesizedExpression : Expression {
+    ParenthesizedExpression(Expression* inner)
+    : mInner(inner) {}
+    ~ParenthesizedExpression() {
+        delete mInner;
+    }
+
+    virtual Type getType(const AST &ast) {
+        return mInner->getType(ast);
+    }
+    virtual std::string toString() {
+        return "(" + mInner->toString() + ")";
+    }
+
+private:
+    Expression* mInner;
+
+    DISALLOW_COPY_AND_ASSIGN(ParenthesizedExpression);
+};
+
+struct AtomExpression : Expression {
+    AtomExpression(Type type, const std::string &value)
+    : mType(type), mValue(value)
+    {}
+
+    virtual Type getType(const AST &ast) {
+        if (mType != Type::UNKOWN) {
+            return mType; 
+        }
+
+        Define *define = ast.getDefinesScope().lookup(mValue);
+
+        if (define == NULL) {
+            return Type::UNKOWN;
+        }
+
+        return define->getExpressionType();
+    }
+    virtual std::string toString() {
+        return mValue;
+    }
+
+private:
+    Type mType;
+    std::string mValue;
+
+    DISALLOW_COPY_AND_ASSIGN(AtomExpression);
+};
+
+struct UnaryExpression : Expression {
+    UnaryExpression(std::string op, Expression* rhs)
+    : mOp(op), mRhs(rhs)
+    {}
+    ~UnaryExpression() {
+        delete mRhs;
+    }
+
+    virtual Type getType(const AST &ast) {
+        return mRhs->getType(ast);
+    }
+    virtual std::string toString() {
+        return mOp + mRhs->toString();
+    }
+
+private:
+    std::string mOp;
+    Expression* mRhs;
+
+    DISALLOW_COPY_AND_ASSIGN(UnaryExpression);
+};
+
+struct BinaryExpression : Expression {
+    BinaryExpression(Expression *lhs, std::string op, Expression* rhs)
+    : mLhs(lhs), mOp(op), mRhs(rhs)
+    {}
+    ~BinaryExpression() {
+        delete mLhs;
+        delete mRhs;
+    }
+
+    virtual Type getType(const AST &ast) {
+        return coalesceTypes(mLhs->getType(ast), mRhs->getType(ast));
+    }
+    virtual std::string toString() {
+        return mLhs->toString() + " " + mOp + " " + mRhs->toString();
+    }
+
+private:
+    Expression* mLhs;
+    std::string mOp;
+    Expression* mRhs;
+
+    DISALLOW_COPY_AND_ASSIGN(BinaryExpression);
+};
+
+struct TernaryExpression : Expression {
+    TernaryExpression(Expression *lhs, Expression *mhs, Expression* rhs)
+    : mLhs(lhs), mMhs(mhs), mRhs(rhs)
+    {}
+    ~TernaryExpression() {
+        delete mLhs;
+        delete mMhs;
+        delete mRhs;
+    }
+
+    virtual Type getType(const AST &ast) {
+        return coalesceTypes(mMhs->getType(ast), mRhs->getType(ast));
+    }
+    virtual std::string toString() {
+        return mLhs->toString() + " ? " + mMhs->toString() + " : " + mRhs->toString();
+    }
+
+private:
+    Expression* mLhs;
+    Expression* mMhs;
+    Expression* mRhs;
+
+    DISALLOW_COPY_AND_ASSIGN(TernaryExpression);
+};
+
+struct ArraySubscript : Expression {
+    ArraySubscript(std::string id, Expression* subscript)
+    : mId(id), mSubscript(subscript)
+    {}
+    ~ArraySubscript() {
+        delete mSubscript;
+    }
+
+    virtual Type getType(const AST &) {
+        return Type::UNKOWN;
+    }
+    virtual std::string toString() {
+        return mId + "[" + mSubscript->toString() + "]";
+    }
+
+private:
+    std::string mId;
+    Expression* mSubscript;
+
+    DISALLOW_COPY_AND_ASSIGN(ArraySubscript);
+};
+
+struct FunctionCall : Expression {
+    FunctionCall(std::string id, std::vector<Expression *> *args)
+    : mId(id), mArgs(args)
+    {}
+    ~FunctionCall() {
+        if(mArgs != NULL) {
+            for(auto* args : *mArgs) {
+                delete args;
+            }
+        }
+        delete mArgs;
+    }
+
+    virtual Type getType(const AST &) {
+        return Type::UNKOWN;
+    }
+    virtual std::string toString() {
+        std::string out = mId + "(";
+
+        for (auto it = mArgs->begin(); it != mArgs->end(); ++it) {
+            if (it != mArgs->begin()) {
+                out += ", ";
+            }
+
+            out += (*it)->toString();
+        }
+
+        return out;
+    }
+
+private:
+    std::string mId;
+    std::vector<Expression *> *mArgs;
+
+    DISALLOW_COPY_AND_ASSIGN(FunctionCall);
+};
+
+// static
+Expression *Expression::parenthesize(Expression *inner) {
+    return new ParenthesizedExpression(inner);
+}
+
+// static
+Expression *Expression::atom(Type type, const std::string &value) {
+    return new AtomExpression(type, value);
+}
+
+// static
+Expression *Expression::unary(std::string op, Expression *rhs) {
+    return new UnaryExpression(op, rhs);
+}
+
+// static
+Expression *Expression::binary(Expression *lhs, std::string op, Expression *rhs) {
+    return new BinaryExpression(lhs, op, rhs);
+}
+
+// static
+Expression *Expression::ternary(Expression *lhs, Expression *mhs, Expression *rhs) {
+    return new TernaryExpression(lhs, mhs, rhs);
+}
+
+// static
+Expression *Expression::arraySubscript(std::string id, Expression *subscript) {
+    return new ArraySubscript(id, subscript);
+}
+
+// static
+Expression *Expression::functionCall(std::string id, std::vector<Expression *> *args) {
+    return new FunctionCall(id, args);
+}
+
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Expression.h b/c2hal/Expression.h
new file mode 100644
index 0000000..13ac96d
--- /dev/null
+++ b/c2hal/Expression.h
@@ -0,0 +1,86 @@
+/*
+ * 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 EXPRESSION_H_
+#define EXPRESSION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+
+namespace android {
+
+struct AST;
+struct Define;
+
+struct Expression {
+    Expression() {}
+    virtual ~Expression() {}
+
+    enum Type {
+        S32 = 0, // 0b00
+        S64 = 1, // 0b01
+        U32 = 2, // 0b10
+        U64 = 3, // 0b11
+        UNKOWN = -1
+    };
+
+    static std::string getTypeDescription(Type type) {
+        switch (type) {
+            case S32: return "S32";
+            case S64: return "S64";
+            case U32: return "U32";
+            case U64: return "U64";
+            case UNKOWN:
+            default:
+                return "UNKOWN";
+        }
+    }
+
+    static std::string getTypeName(Type type) {
+        switch (type) {
+            case S32: return "int32_t";
+            case S64: return "int64_t";
+            case U32: return "uint32_t";
+            case U64: return "uint64_t";
+            case UNKOWN:
+            default:
+                return "/* UNKOWN */";
+        }
+    }
+
+    static Type integralType(std::string integer);
+    static Type coalesceTypes(Type lhs, Type rhs);
+
+    static Expression *parenthesize(Expression *inner);
+    static Expression *atom(Type type, const std::string &value);
+    static Expression *unary(std::string op, Expression *rhs);
+    static Expression *binary(Expression *lhs, std::string op, Expression *rhs);
+    static Expression *ternary(Expression *lhs, Expression *mhs, Expression *rhs);
+    static Expression *arraySubscript(std::string id, Expression *subscript);
+    static Expression *functionCall(std::string id, std::vector<Expression *> *args);
+
+    virtual Type getType(const AST &scope) = 0;
+    virtual std::string toString() = 0;
+
+private:
+
+    DISALLOW_COPY_AND_ASSIGN(Expression);
+};
+
+}  // namespace android
+
+#endif  // EXPRESSION_H_
\ No newline at end of file
diff --git a/c2hal/FunctionDeclaration.cpp b/c2hal/FunctionDeclaration.cpp
new file mode 100644
index 0000000..3129fee
--- /dev/null
+++ b/c2hal/FunctionDeclaration.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 "FunctionDeclaration.h"
+#include "VarDeclaration.h"
+#include "Type.h"
+
+namespace android {
+
+FunctionDeclaration::FunctionDeclaration(Type* type,
+                  const std::string &name,
+                  std::vector<Declaration *> *params)
+    : Declaration(name),
+      mType(type),
+      mParams(params)
+    {}
+
+FunctionDeclaration::~FunctionDeclaration() {
+    delete mType;
+
+    if(mParams != NULL) {
+        for(auto* param : *mParams) {
+            delete param;
+        }
+    }
+    delete mParams;
+}
+
+
+const Type* FunctionDeclaration::getType() const {
+    return mType;
+}
+
+void FunctionDeclaration::generateSource(Formatter &out) const {
+    out << getName();
+
+    generateParams(out);
+
+    if (!getType()->isVoid()) {
+        out << " generates ("
+            << getType()->decorateName(getName() + "_ret")
+            << ")";
+    }
+
+    out << ";\n";
+}
+
+void FunctionDeclaration::generateParameterSource(Formatter &out) const {
+    out << getType()->decorateName("(*" + getName() + ")");
+
+    generateParams(out);
+}
+
+void FunctionDeclaration::processContents(AST &) {
+    if (mParams->size() == 1 &&
+        (*mParams)[0]->decType() == VarDeclaration::type()) {
+
+        VarDeclaration* var = (VarDeclaration *)(*mParams)[0];
+        if (var->getType()->isVoid()) {
+            mParams->clear();
+        }
+    }
+}
+
+void FunctionDeclaration::generateParams(Formatter &out) const {
+    out << "(";
+
+    for (auto it = mParams->begin(); it != mParams->end(); ++it) {
+        if (it != mParams->begin()) {
+            out << ", ";
+        }
+
+        (*it)->generateParameterSource(out);
+    }
+
+    out << ")";
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/FunctionDeclaration.h b/c2hal/FunctionDeclaration.h
new file mode 100644
index 0000000..1791102
--- /dev/null
+++ b/c2hal/FunctionDeclaration.h
@@ -0,0 +1,55 @@
+/*
+ * 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 FUNCTION_DECLARATION_H_
+#define FUNCTION_DECLARATION_H_
+
+#include "Declaration.h"
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+
+namespace android {
+
+struct Declaration;
+struct Type;
+
+struct FunctionDeclaration : Declaration {
+    FunctionDeclaration(Type* type,
+                  const std::string &name,
+                  std::vector<Declaration *> *params);
+    ~FunctionDeclaration();
+
+    const Type * getType() const;
+
+    static std::string type() { return "function"; }
+    const std::string decType() const override { return type(); }
+
+    void generateSource(Formatter &out) const override;
+    void generateParameterSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+private:
+    const Type *mType;
+    std::vector<Declaration *> *mParams;
+
+    void generateParams(Formatter &out) const;
+
+    DISALLOW_COPY_AND_ASSIGN(FunctionDeclaration);
+};
+
+}  // namespace android
+
+#endif  // FUNCTION_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Include.cpp b/c2hal/Include.cpp
new file mode 100644
index 0000000..8ee72f8
--- /dev/null
+++ b/c2hal/Include.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "Include.h"
+
+namespace android {
+
+Include::Include(const std::string &name, bool isLibrary)
+    : Declaration(name), mIsLibrary(isLibrary)
+    {}
+
+Include::~Include() {}
+
+bool Include::isLibrary() const {
+    return mIsLibrary;
+}
+
+void Include::generateSource(Formatter &out) const {
+    out << "// import "
+        << getName();
+
+    if (isLibrary()) {
+        out << "/* library file */";
+    } else {
+        out << "/* local file */";
+    }
+
+    out << "\n";
+}
+
+void Include::processContents(AST &) {
+    // nothing to do
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Include.h b/c2hal/Include.h
new file mode 100644
index 0000000..21988ff
--- /dev/null
+++ b/c2hal/Include.h
@@ -0,0 +1,48 @@
+/*
+ * 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 INCLUDE_H_
+#define INCLUDE_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include "../Formatter.h"
+#include "Declaration.h"
+
+namespace android {
+
+struct Include : Declaration {
+    Include(const std::string &name, bool isLibrary);
+    ~Include();
+
+    static std::string type() { return "include"; }
+    const std::string decType() const override { return type(); }
+
+    void generateSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+    bool isLibrary() const;
+
+private:
+    const bool mIsLibrary;
+
+    DISALLOW_COPY_AND_ASSIGN(Include);
+};
+
+}  // namespace android
+
+#endif  // INCLUDE_H_
\ No newline at end of file
diff --git a/c2hal/Note.cpp b/c2hal/Note.cpp
new file mode 100644
index 0000000..a9422fc
--- /dev/null
+++ b/c2hal/Note.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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 "Note.h"
+
+namespace android {
+
+Note::Note(const std::string &name)
+    : Declaration(name)
+    {}
+
+Note::~Note() {}
+
+void Note::generateSource(Formatter &out) const {
+    out << "/* NOTE:\n";
+
+    out.indent();
+    out << getName();
+    out.unindent();
+
+    out << "\n*/\n";
+}
+
+void Note::processContents(AST &) {
+    // nothing to do
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Note.h b/c2hal/Note.h
new file mode 100644
index 0000000..679c773
--- /dev/null
+++ b/c2hal/Note.h
@@ -0,0 +1,49 @@
+/*
+ * 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 NOTE_DECLARATION_H_
+#define NOTE_DECLARATION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+
+namespace android {
+
+/* This class is used to represent declarations or notes
+ * which are otherwise not included in a HIDL HAL
+ */
+struct Note : Declaration {
+    Note(const std::string &name);
+    ~Note();
+
+    static std::string type() { return "note"; }
+    const std::string decType() const override { return type(); }
+
+    void generateSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+private:
+    std::string mExpression;
+
+    DISALLOW_COPY_AND_ASSIGN(Note);
+};
+
+}  // namespace android
+
+#endif  // NOTE_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Scope.h b/c2hal/Scope.h
new file mode 100644
index 0000000..7ff77ef
--- /dev/null
+++ b/c2hal/Scope.h
@@ -0,0 +1,84 @@
+/*
+ * 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 SCOPE_H_
+#define SCOPE_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace android {
+
+/* This class is used to represent declarations or notes
+ * which are otherwise not included in a HIDL HAL
+ */
+template<typename T>
+struct Scope {
+    Scope() {}
+    ~Scope() {}
+
+    void enter(std::string name, T item);
+    void leave(std::string name);
+
+    T lookup(std::string name) const;
+
+private:
+    std::map<std::string, T> mScopeContents;
+
+    DISALLOW_COPY_AND_ASSIGN(Scope);
+};
+
+template<typename T>
+void Scope<T>::enter(std::string name, T item) {
+    auto it = mScopeContents.find(name);
+
+    if (it != mScopeContents.end()) {
+        LOG(WARNING) << "Redeclaring variable in scope: " << name;
+        return;
+    }
+
+    mScopeContents[name] = item;
+}
+
+template<typename T>
+void Scope<T>::leave(std::string name) {
+    auto it = mScopeContents.find(name);
+
+    if (it == mScopeContents.end()) {
+        LOG(WARNING) << "Tried to undefined already undefined value in scope: " << name;
+        return;
+    }
+
+    mScopeContents.erase(it);
+}
+
+template<typename T>
+T Scope<T>::lookup(std::string name) const {
+    auto it = mScopeContents.find(name);
+
+    if (it == mScopeContents.end()) {
+        return NULL;
+    }
+
+    return (*it).second;
+}
+
+}  // namespace android
+
+#endif  // SCOPE_H_
\ No newline at end of file
diff --git a/c2hal/Type.cpp b/c2hal/Type.cpp
new file mode 100644
index 0000000..28e4618
--- /dev/null
+++ b/c2hal/Type.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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 "Type.h"
+#include <sstream>
+
+namespace android {
+
+Type::Type(std::vector<Qualifier*> *qualifiers)
+    : mQualifiers(qualifiers)
+    {}
+
+Type::~Type() {
+    delete mArray;
+
+    if(mQualifiers != NULL) {
+        for(auto* qual : *mQualifiers) {
+            delete qual;
+        }
+    }
+    delete mQualifiers;}
+
+
+void Type::setArray(Expression *array) {
+    mArray = array;
+}
+
+const std::string Type::decorateName(const std::string &name) const {
+    std::stringstream ss;
+
+    std::string special = getSpecialTypeName();
+
+    if(special.empty()) {
+        ss << getPreHidlType()
+           << name
+           << getPostHidlType();
+    } else {
+        ss << special
+           << " "
+           << name;
+    }
+
+    return ss.str();
+}
+
+// static
+std::map<std::string, std::string> Type::kCToHidlMap = {
+    { "int", "int32_t" },
+    { "native_handle_t", "handle" },
+
+    // { "hidl_string", "string" },
+    // { "hidl_vec", "vec"},
+};
+
+// static
+const std::string Type::cToHidlType(const std::string &cType) {
+    auto it = kCToHidlMap.find(cType);
+
+    if (it == kCToHidlMap.end()) {
+        return cType;
+    }
+
+    return (*it).second;
+}
+
+const std::string Type::getPreHidlType() const {
+    if (mQualifiers == NULL) {
+        return "";
+    }
+
+    std::stringstream ss;
+
+    for(auto* qualifier : *mQualifiers) {
+        switch(qualifier->qualification) {
+            case Type::Qualifier::STRUCT:
+            case Type::Qualifier::UNION:
+            case Type::Qualifier::ENUM:
+            case Type::Qualifier::POINTER:
+            case Type::Qualifier::CONST:
+                ss << "/* "
+                   << Type::qualifierText(qualifier->qualification)
+                   << " */ ";
+                break;
+            case Type::Qualifier::ID:
+                ss << cToHidlType(qualifier->id) << " ";
+                break;
+            case Type::Qualifier::GENERICS:
+                ss << "<"
+                   << qualifier->generics->decorateName("")
+                   << "> ";
+                break;
+            default: {
+                ss << Type::qualifierText(qualifier->qualification)
+                   << " ";
+            }
+        }
+    }
+
+    return ss.str();
+}
+
+const std::string Type::getPostHidlType() const {
+    std::stringstream ss;
+
+    if (mArray != NULL) {
+        ss << "[" << mArray->toString() << "]";
+    }
+
+    return ss.str();
+}
+
+const std::string Type::getRawQualifierList() const {
+    if (mQualifiers == NULL) {
+        return "";
+    }
+
+    std::stringstream ss;
+
+    for(auto* qualifier : *mQualifiers) {
+        ss << Type::qualifierText(qualifier->qualification) << " ";
+    }
+
+    return ss.str();
+}
+
+const std::string Type::getSpecialTypeName() const {
+    // this makes for a relatively expensive comparison, but it is
+    // readable until the converstion get nailed down.
+    std::string qualifiers = getRawQualifierList();
+
+    if (qualifiers == "const ID * " ||
+        qualifiers == "ID * ") {
+
+        std::string id = mQualifiers->at(mQualifiers->size() - 2)->id;
+
+        if (id == "char") {
+            return "string";
+        } else {
+            // can't tell if it's a hidl_vec or a pointer
+            // return "vec<" + id + ">";
+            return "";
+        }
+    }
+
+    return "";
+}
+
+bool Type::isVoid() const {
+    if (mQualifiers->size() == 0) {
+        return true;
+    }
+
+    return mQualifiers->size() == 1 &&
+           (*mQualifiers)[0]->qualification == Type::Qualifier::VOID;
+}
+
+
+std::string Type::removeLastId() {
+    if(mQualifiers == NULL || mQualifiers->size() == 0) {
+        return "";
+    }
+
+    Qualifier *last = (*mQualifiers)[mQualifiers->size() - 1];
+
+    if(last == NULL || last->qualification != Qualifier::ID) {
+        return "";
+    }
+
+    std::string ret{last->id};
+
+    mQualifiers->erase(mQualifiers->end() - 1);
+
+    return ret;
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Type.h b/c2hal/Type.h
new file mode 100644
index 0000000..afb1496
--- /dev/null
+++ b/c2hal/Type.h
@@ -0,0 +1,112 @@
+/*
+ * 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 TYPE_H_
+#define TYPE_H_
+
+#include "Expression.h"
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace android {
+
+struct Type {
+
+    struct Qualifier {
+
+        enum Qualification {
+            NONE = 0,
+            STRUCT,
+            UNION,
+            SIGNED,
+            UNSIGNED,
+            VOID,
+            POINTER,
+            CONST,
+            GENERICS,
+            ID,
+            ENUM
+        } qualification;
+
+        union {
+            std::string id;
+            Type *generics;
+        };
+
+        Qualifier(Qualification qualification)
+        : qualification(qualification) {}
+        Qualifier(Qualification qualification, std::string id)
+        : qualification(qualification), id(id) {}
+        Qualifier(Qualification qualification, Type* generics)
+        : qualification(qualification), generics(generics) {}
+
+        ~Qualifier() {
+            if (qualification == GENERICS) {
+                delete generics;
+            }
+        }
+    };
+
+    Type(std::vector<Qualifier*> *qualifiers);
+    ~Type();
+
+    static std::string qualifierText(Qualifier::Qualification qual) {
+        switch(qual) {
+            case Qualifier::STRUCT: return "struct";
+            case Qualifier::UNION: return "union";
+            case Qualifier::ENUM: return "enum";
+            case Qualifier::SIGNED: return "signed";
+            case Qualifier::UNSIGNED: return "unsigned";
+            case Qualifier::VOID: return "void";
+            case Qualifier::POINTER: return "*";
+            case Qualifier::CONST: return "const";
+            case Qualifier::ID: return "ID";
+            case Qualifier::NONE: return "";
+            default: return "/* UNKNOWN TYPE QUALIFIER */";
+        }
+    }
+
+    void setArray(Expression *array);
+
+    const std::string decorateName(const std::string &name) const;
+
+    bool isVoid() const;
+    std::string removeLastId();
+
+private:
+
+    static std::map<std::string, std::string> kCToHidlMap;
+    static const std::string cToHidlType(const std::string &cType);
+
+    const std::string getPreHidlType() const;
+    const std::string getPostHidlType() const;
+
+    const std::string getRawQualifierList() const;
+    const std::string getSpecialTypeName() const;
+
+    std::vector<Qualifier*> *mQualifiers = NULL;
+    Expression *mArray = NULL;
+
+    DISALLOW_COPY_AND_ASSIGN(Type);
+};
+
+}  // namespace android
+
+#endif  // TYPE_H_
\ No newline at end of file
diff --git a/c2hal/TypeDef.cpp b/c2hal/TypeDef.cpp
new file mode 100644
index 0000000..529bf99
--- /dev/null
+++ b/c2hal/TypeDef.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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 "TypeDef.h"
+
+namespace android {
+
+TypeDef::TypeDef(const std::string &name, Declaration* declaration)
+    : Declaration(name), mDeclaration(declaration)
+    {}
+
+TypeDef::~TypeDef() {}
+
+void TypeDef::generateSource(Formatter &out) const {
+    out << "typedef ";
+
+    mDeclaration->generateParameterSource(out);
+
+    out << ";\n";
+}
+
+void TypeDef::processContents(AST &ast) {
+    mDeclaration->processContents(ast);
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/TypeDef.h b/c2hal/TypeDef.h
new file mode 100644
index 0000000..2f4de5a
--- /dev/null
+++ b/c2hal/TypeDef.h
@@ -0,0 +1,46 @@
+/*
+ * 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 TYPE_DEF_H_
+#define TYPE_DEF_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+
+namespace android {
+
+struct TypeDef : Declaration {
+    TypeDef(const std::string &name, Declaration* declaration);
+    ~TypeDef();
+
+    static std::string type() { return "typedef"; }
+    const std::string decType() const override { return type(); }
+
+    void generateSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+private:
+    Declaration* mDeclaration;
+
+    DISALLOW_COPY_AND_ASSIGN(TypeDef);
+};
+
+}  // namespace android
+
+#endif  // TYPE_DEF_H_
\ No newline at end of file
diff --git a/c2hal/VarDeclaration.cpp b/c2hal/VarDeclaration.cpp
new file mode 100644
index 0000000..6f5e710
--- /dev/null
+++ b/c2hal/VarDeclaration.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "VarDeclaration.h"
+
+namespace android {
+
+VarDeclaration::VarDeclaration(Type *type, const std::string &name)
+    : Declaration(name),
+      mType(type)
+    {}
+
+VarDeclaration::~VarDeclaration() {
+    delete mType;
+}
+
+Type* VarDeclaration::getType() const {
+    return mType;
+}
+
+void VarDeclaration::generateSource(Formatter &out) const {
+    out << getType()->decorateName(getName())
+        << ";\n";
+}
+
+void VarDeclaration::generateParameterSource(Formatter &out) const {
+    out << getType()->decorateName(getName());
+}
+
+void VarDeclaration::processContents(AST &) {
+    // nothing to do
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/c2hal/VarDeclaration.h b/c2hal/VarDeclaration.h
new file mode 100644
index 0000000..e8ac2b4
--- /dev/null
+++ b/c2hal/VarDeclaration.h
@@ -0,0 +1,46 @@
+/*
+ * 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 VARDECLARATION_H_
+#define VARDECLARATION_H_
+
+#include "Declaration.h"
+#include "Type.h"
+
+namespace android {
+
+struct VarDeclaration : Declaration{
+    VarDeclaration(Type *type, const std::string &name);
+    ~VarDeclaration();
+
+    Type* getType() const;
+
+    static std::string type() { return "var"; }
+    const std::string decType() const override { return type(); }
+
+    void generateSource(Formatter &out) const override;
+    void generateParameterSource(Formatter &out) const override;
+    void processContents(AST &ast) override;
+
+private:
+    Type *mType;
+
+    DISALLOW_COPY_AND_ASSIGN(VarDeclaration);
+};
+
+}  // namespace android
+
+#endif  // VARDECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/c2hal_l.ll b/c2hal/c2hal_l.ll
new file mode 100644
index 0000000..089dba6
--- /dev/null
+++ b/c2hal/c2hal_l.ll
@@ -0,0 +1,313 @@
+/*
+ * 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.
+ */
+
+D             [0-9]
+L             [a-zA-Z_]
+AN            [a-zA-Z_0-9]
+H             [a-fA-F_0-9]
+E             [Ee][+-]?{D}+
+FS            (f|F|l|L)
+IS            (u|U|l|L)*
+S             [ \t]
+DOT           [.]
+PATH          ({DOT}|{AN}|\/|-)+
+ID            {L}{AN}*
+
+%{
+
+#include "AST.h"
+#include "Declaration.h"
+#include "Type.h"
+#include "VarDeclaration.h"
+#include "FunctionDeclaration.h"
+#include "CompositeDeclaration.h"
+#include "Define.h"
+#include "Include.h"
+#include "EnumVarDeclaration.h"
+#include "Note.h"
+#include "TypeDef.h"
+#include "Expression.h"
+
+#include <assert.h>
+#include <utils/Errors.h>
+
+#include "c2hal_y.h"
+
+using namespace android;
+
+int check_type(yyscan_t yyscanner, struct yyguts_t *yyg);
+
+// TODO convert to parse params/lex params
+
+extern int start_token;
+
+extern std::string last_comment;
+
+// :(
+extern int numB;
+extern std::string functionText;
+
+extern std::string defineText;
+extern std::string otherText;
+
+extern bool isOpenGl;
+
+#define YY_USER_ACTION yylloc->first_line = yylineno;
+
+#define ID_UNLESS_OPEN_GL(OPEN_GL_CODE)                                  \
+        do {                                                             \
+            if (isOpenGl) {                                              \
+                OPEN_GL_CODE                                             \
+            } else {                                                     \
+                yylval->str = strdup(yytext);                            \
+                return ID;                                               \
+            }                                                            \
+        } while(0)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#pragma clang diagnostic ignored "-Wdeprecated-register"
+
+%}
+
+%option yylineno
+%option reentrant
+%option bison-bridge
+%option bison-locations
+%option extra-type="android::AST *"
+
+%x COMMENT_STATE
+%x INCLUDE_STATE
+%x COPY_DECL_STATE
+%x FUNCTION_STATE
+%x DEFINE_STATE
+%x DEFINE_SLURP_STATE
+
+%%
+%{
+    if (start_token) {
+        int token = start_token;
+        start_token = 0;
+        return token;
+    }
+%}
+
+"\n"                              { /* needed for yylineno to update */ }
+
+\/\*([^*]|\*+[^*\/])*\*+\/        { last_comment = strdup(yytext); }
+
+"//"[^\r\n]*                      { /* skip C++ style comment */ }
+
+"__BEGIN_DECLS"                   { /* macro'd 'extern "C" {' if CPP or nothing */ }
+"__END_DECLS"                     { /* '}' */ }
+
+"__attribute__((__packed__))"     { /* ignore */ }
+"__attribute__((packed))"         { /* ignore */ }
+"__attribute__((__deprecated__))" { /* ignore */ }
+
+"EGLAPIENTRYP"                    { ID_UNLESS_OPEN_GL(return '*';); }
+"EGLAPIENTRY"                     { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); }
+"GL_APIENTRYP"                    { ID_UNLESS_OPEN_GL(return '*';); }
+"GL_APIENTRY"                     { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); }
+"GL_APICALL"                      { ID_UNLESS_OPEN_GL(/* __attribute__((visibility("default"))) */); }
+
+"#include"                        { BEGIN(INCLUDE_STATE); return INCLUDE; }
+<INCLUDE_STATE>"<"                { return '<'; }
+<INCLUDE_STATE>">"                { return '>'; }
+<INCLUDE_STATE>"\""               { return '"'; }
+<INCLUDE_STATE>"\n"               { BEGIN(INITIAL); }
+<INCLUDE_STATE>{PATH}             { yylval->str = strdup(yytext); return INCLUDE_FILE; }
+<INCLUDE_STATE>.                  { /* ignore other characters */ }
+
+"static"|"inline"                 {
+                                    BEGIN(FUNCTION_STATE);
+                                    functionText = strdup(yytext);
+                                    numB = 0;
+                                  }
+<FUNCTION_STATE>[^{}]+            { functionText += yytext; }
+<FUNCTION_STATE>"{"               { functionText += yytext; numB += 1;}
+<FUNCTION_STATE>"}"               {
+                                    functionText += yytext;
+                                    numB -= 1;
+
+                                    // Will fail if unbalanced brackets in
+                                    // strings or comments in the function.
+                                    if (numB <= 0) {
+                                        BEGIN(INITIAL);
+                                        yylval->str = strdup(functionText.c_str());
+                                        return FUNCTION;
+                                    }
+                                   }
+
+"#"{S}*"define"                   { BEGIN(DEFINE_STATE); return DEFINE; }
+<DEFINE_STATE>{ID}                {
+                                    BEGIN(DEFINE_SLURP_STATE);
+                                    defineText = "";
+                                    yylval->str = strdup(yytext);
+                                    return ID;
+                                  }
+<DEFINE_STATE>.                   { /* ignore other characters */ }
+
+<DEFINE_SLURP_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ {
+                                    defineText += yytext;
+                                  }
+<DEFINE_SLURP_STATE>[^\\\n]       { defineText += yytext; }
+<DEFINE_SLURP_STATE>"\\\n"        { defineText += yytext; }
+<DEFINE_SLURP_STATE>"\n"          {
+                                    BEGIN(INITIAL);
+                                    yylval->str = strdup(defineText.c_str());
+                                    return DEFINE_SLURP;
+                                  }
+
+"using"                           { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); }
+"#"{S}*{L}+                       { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); }
+<COPY_DECL_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ {
+                                    otherText += yytext;
+                                  }
+<COPY_DECL_STATE>[^\\\n]          { otherText += yytext; }
+<COPY_DECL_STATE>"\\\n"           { otherText += yytext; }
+<COPY_DECL_STATE>"\n"             {
+                                    BEGIN(INITIAL);
+                                    yylval->str = strdup(otherText.c_str());
+                                    // decls/macros we want to preserve
+                                    // in the output, but there is nothing
+                                    // special to do about them yet
+                                    return OTHER_STATEMENT;
+                                  }
+
+"struct"                          { return STRUCT; }
+"union"                           { return UNION; }
+"enum"                            { return ENUM; }
+"const"                           { return CONST; }
+"typedef"                         { return TYPEDEF; }
+"void"                            { return VOID; }
+"unsigned"                        { return UNSIGNED; }
+"signed"                          { return SIGNED; }
+"namespace"                       { return NAMESPACE; }
+"extern"                          { return EXTERN; }
+"\"C\""                           { return C_STRING; }
+
+{ID}                              { yylval->str = strdup(yytext); return ID; }
+0[xX]{H}+{IS}?                    { yylval->str = strdup(yytext); return INTEGRAL_VALUE; }
+0{D}+{IS}?                        { yylval->str = strdup(yytext); return INTEGRAL_VALUE; }
+{D}+{IS}?                         { yylval->str = strdup(yytext); return INTEGRAL_VALUE; }
+
+{D}+{E}{FS}?                      { yylval->str = strdup(yytext); return VALUE; }
+{D}+\.{E}?{FS}?                   { yylval->str = strdup(yytext); return VALUE; }
+{D}*\.{D}+{E}?{FS}?               { yylval->str = strdup(yytext); return VALUE; }
+L?\"(\\.|[^\\"])*\"               { yylval->str = strdup(yytext); return VALUE; }
+
+"("                               { return '('; }
+")"                               { return ')'; }
+"<"                               { return '<'; }
+">"                               { return '>'; }
+"{"                               { return '{'; }
+"}"                               { return '}'; }
+"["                               { return '['; }
+"]"                               { return ']'; }
+"?"                               { return '?'; }
+":"                               { return ':'; }
+"*"                               { return '*'; }
+";"                               { return ';'; }
+","                               { return ','; }
+"="                               { return '='; }
+"+"                               { return '+'; }
+"-"                               { return '-'; }
+"/"                               { return '/'; }
+"%"                               { return '%'; }
+"&"                               { return '&'; }
+"|"                               { return '|'; }
+"^"                               { return '^'; }
+"~"                               { return '~'; }
+"<<"                              { return LSHIFT; }
+">>"                              { return RSHIFT; }
+
+"..."                             { return VARARGS; }
+
+.                                 { /* ignore other characters */ }
+
+%%
+
+#pragma clang diagnostic pop
+
+// allows us to specify what start symbol will be used in the grammar
+int start_token;
+bool should_report_errors;
+
+std::string last_comment;
+
+// this is so frowned upon on so many levels, but here vars are so that we can
+// slurp up function text as a string and don't have to implement
+// the *entire* grammar of C (and C++ in some files) just to parse headers
+int numB;
+std::string functionText;
+
+std::string defineText;
+std::string otherText;
+
+bool isOpenGl;
+
+int yywrap(yyscan_t) {
+    return 1;
+}
+
+status_t parseFile(AST *ast) {
+    FILE *file = fopen(ast->getFilename().c_str(), "rb");
+
+    if (file == NULL) {
+        return -errno;
+    }
+
+    start_token = START_HEADER;
+    isOpenGl = ast->isOpenGl();
+    should_report_errors = true;
+
+    yyscan_t scanner;
+    yylex_init_extra(ast, &scanner);
+    ast->setScanner(scanner);
+
+    yyset_in(file, scanner);
+    int res = yyparse(ast);
+
+    yylex_destroy(scanner);
+    ast->setScanner(NULL);
+
+    fclose(file);
+    file = NULL;
+
+    return res;
+}
+
+status_t parseExpression(AST *ast, std::string str) {
+    start_token = START_EXPR;
+    isOpenGl = ast->isOpenGl();
+    should_report_errors = false;
+
+    yyscan_t scanner;
+    yylex_init_extra(ast, &scanner);
+    ast->setScanner(scanner);
+
+    YY_BUFFER_STATE buf = yy_scan_string(str.c_str(), scanner);
+
+    int res = yyparse(ast);
+
+    yy_delete_buffer(buf, scanner);
+
+    yylex_destroy(scanner);
+    ast->setScanner(NULL);
+
+    return res;
+}
diff --git a/c2hal/c2hal_y.yy b/c2hal/c2hal_y.yy
new file mode 100644
index 0000000..4331025
--- /dev/null
+++ b/c2hal/c2hal_y.yy
@@ -0,0 +1,485 @@
+/*
+ * 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 "AST.h"
+#include "Declaration.h"
+#include "Type.h"
+#include "VarDeclaration.h"
+#include "FunctionDeclaration.h"
+#include "CompositeDeclaration.h"
+#include "Define.h"
+#include "Include.h"
+#include "EnumVarDeclaration.h"
+#include "Note.h"
+#include "TypeDef.h"
+#include "Expression.h"
+
+#include "c2hal_y.h"
+
+#include <stdio.h>
+#include <utils/String8.h>
+#include <algorithm>
+
+using namespace android;
+
+extern int yylex(YYSTYPE *yylval_param, YYLTYPE *llocp, void *);
+
+int yyerror(YYLTYPE *llocp, AST *, const char *s) {
+    extern bool should_report_errors;
+
+    if (!should_report_errors) {
+      return 0;
+    }
+
+    fflush(stdout);
+    LOG(ERROR) << " "
+               << s
+               << " near line "
+               << llocp->first_line;
+
+    return 0;
+}
+
+#define scanner ast->scanner()
+
+std::string get_last_comment() {
+    extern std::string last_comment;
+
+    std::string ret{last_comment};
+
+    // clear the last comment now that it's been taken
+    last_comment = "";
+
+    return ret;
+}
+
+%}
+
+%parse-param { android::AST *ast }
+%lex-param   { void *scanner }
+%locations
+%pure-parser
+%glr-parser
+
+%token START_HEADER
+%token START_EXPR
+
+%token STRUCT
+%token UNION
+%token ENUM
+%token CONST
+%token VOID
+%token INCLUDE
+%token DEFINE
+%token TYPEDEF
+%token UNSIGNED
+%token SIGNED
+%token LSHIFT
+%token RSHIFT
+%token VARARGS
+%token NAMESPACE
+%token EXTERN
+%token C_STRING
+
+%left ','
+%right '?' ':'
+%left '|'
+%left '^'
+%left '&'
+%left RSHIFT LSHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right '~' '!' UMINUS UPLUS
+%left ARRAY_SUBSCRIPT FUNCTION_CALL
+
+%token<str> ID
+%token<str> COMMENT
+%token<str> VALUE
+%token<str> INTEGRAL_VALUE
+%token<str> INCLUDE_FILE
+%token<str> FUNCTION
+%token<str> DEFINE_SLURP
+%token<str> OTHER_STATEMENT
+
+%type<expression> opt_array
+%type<expression> expr
+%type<expressions> args
+%type<type> type
+%type<qualifier> type_qualifier
+%type<qualifiers> type_qualifiers
+%type<declaration> declaration
+%type<declarations> declarations
+%type<composite> struct_or_union_declaration
+%type<composite> enum_declaration
+%type<param> param
+%type<params> params
+%type<qualification> struct_or_union
+%type<str> opt_id
+%type<include> include
+%type<enum_var> enum_var
+%type<declarations> enum_vars
+
+%start parse_selector
+
+%union {
+    const char *str;
+    int count;
+    android::Declaration *declaration;
+    android::CompositeDeclaration *composite;
+    std::vector<android::Declaration *> *declarations;
+    android::EnumVarDeclaration *enum_var;
+    android::Declaration *param;
+    std::vector<android::Declaration *> *params;
+    android::Type *type;
+    android::Type::Qualifier *qualifier;
+    android::Type::Qualifier::Qualification qualification;
+    std::vector<android::Type::Qualifier*> *qualifiers;
+    android::Include *include;
+    std::vector<android::Include *> *includes;
+    android::Expression *expression;
+    std::vector<android::Expression *> *expressions;
+}
+
+%%
+
+parse_selector
+    : START_HEADER header
+    | START_EXPR expr_parser
+    ;
+
+expr_parser
+    : expr
+      {
+        ast->setExpression($1);
+      }
+    ;
+
+header
+    : declarations /* well, we are a header file */
+      {
+        std::reverse($1->begin(), $1->end());
+        ast->setDeclarations($1);
+      }
+    ;
+
+declarations
+    : /* EMPTY */
+      {
+        $$ = new std::vector<Declaration *>;
+      }
+    | declaration declarations
+      {
+        $$ = $2;
+        $$->push_back($1);
+      }
+    | EXTERN C_STRING '{' declarations '}' declarations
+      {
+        $6->push_back(new Note("} // end of extern C"));
+        $6->insert($6->end(), $4->begin(), $4->end());
+        $6->push_back(new Note("extern \"C\" { "));
+        delete $4;
+
+        $$ = $6;
+      }
+    ;
+
+declaration
+    : param ';'
+      {
+        $$ = $1;
+        $$->setComment(get_last_comment());
+      }
+    | struct_or_union_declaration ';'
+      {
+        $$ = $1;
+      }
+    | enum_declaration ';'
+      {
+        $$ = $1;
+      }
+    | TYPEDEF struct_or_union_declaration ';'
+      {
+        // ignore that it is a typedef, for our purposes it doesn't matter
+        $$ = $2;
+      }
+    | TYPEDEF enum_declaration ';'
+      {
+        // ignore that it is a typedef, for our purposes it doesn't matter
+        $$ = $2;
+      }
+    | TYPEDEF param ';' /* looks like 'typedef const int8_t store;' */
+      {
+        $$ = new TypeDef($2->getName(), $2);
+        $$->setComment(get_last_comment());
+      }
+    | DEFINE ID DEFINE_SLURP
+      {
+        $$ = new Define($2, $3);
+        $$->setComment(get_last_comment());
+      }
+    | OTHER_STATEMENT
+      {
+        $$ = new Note($1);
+        $$->setComment(get_last_comment());
+      }
+    | FUNCTION
+      {
+        $$ = new Note($1);
+        $$->setComment(get_last_comment());
+      }
+    | type ID '=' expr ';'
+      {
+        $$ = new Note($1->decorateName($2) + " = " + $4->toString());
+      }
+    | include
+      {
+        $$ = $1;
+        $$->setComment(get_last_comment());
+      }
+    | NAMESPACE ID '{' declarations '}'
+      {
+        $$ = new CompositeDeclaration(Type::Qualifier::STRUCT,
+                                               $2,
+                                               $4);
+
+        get_last_comment(); // clear it
+        $$->setComment("/* from namespace declaration */");
+      }
+    ;
+
+include
+    : INCLUDE '<' INCLUDE_FILE '>'
+      {
+        $$ = new Include($3, true /* isLibrary */);
+      }
+    | INCLUDE '"' INCLUDE_FILE '"'
+      {
+        $$ = new Include($3, false /* isLibrary */);
+      }
+    ;
+
+struct_or_union_declaration
+    : struct_or_union opt_id
+      {
+        $<str>$ = strdup(get_last_comment().c_str());
+      }
+                             '{' declarations '}' opt_id
+      {
+        std::reverse($5->begin(), $5->end());
+        $$ = new CompositeDeclaration($1, $2, $5);
+        $$->setComment($<str>3);
+
+        if(!std::string($7).empty()) {
+          $$->setName($7);
+        }
+      }
+    ;
+
+enum_declaration
+    : ENUM opt_id
+      {
+        $<str>$ = strdup(get_last_comment().c_str());
+      }
+                           '{' enum_vars '}' opt_id
+      {
+        std::reverse($5->begin(), $5->end());
+        $$ = new CompositeDeclaration(Type::Qualifier::ENUM, $2, $5);
+        $$->setComment($<str>3);
+
+        if(!std::string($7).empty()) {
+          $$->setName($7);
+        }
+      }
+    ;
+
+enum_vars
+    : /* EMPTY */
+      {
+        $$ = new std::vector<Declaration *>;
+      }
+    | enum_var /* a comma is optional on the last item */
+      {
+        $$ = new std::vector<Declaration *>;
+        $$->push_back($1);
+      }
+    | enum_var ',' enum_vars
+      {
+        $$ = $3;
+        $$->push_back($1);
+      }
+    ;
+
+enum_var
+    : ID
+      {
+        $$ = new EnumVarDeclaration($1, NULL);
+        $$->setComment(get_last_comment());
+      }
+    | ID '=' expr
+      {
+        $$ = new EnumVarDeclaration($1, $3);
+        $$->setComment(get_last_comment());
+      }
+    ;
+
+params
+    : /* EMPTY */
+      {
+        $$ = new std::vector<Declaration *>;
+      }
+    | param
+      {
+        $$ = new std::vector<Declaration *>;
+        $$->push_back($1);
+      }
+    | param ',' params
+      {
+        $$ = $3;
+        $$->push_back($1);
+      }
+    ;
+
+param
+    : type opt_array
+      {
+        $1->setArray($2);
+
+        // allow for either "const int myvar" or "const int"
+        // as a parameter declaration
+        std::string lastId = $1->removeLastId();
+
+        $$ = new VarDeclaration($1, lastId);
+      }
+    | type '(' '*' ID opt_array ')' '(' params ')'
+      {
+        $1->setArray($5);
+        std::reverse($8->begin(), $8->end());
+        $$ = new FunctionDeclaration($1, $4, $8);
+      }
+    | type ID '(' params ')'
+      {
+        std::reverse($4->begin(), $4->end());
+        $$ = new FunctionDeclaration($1, $2, $4);
+      }
+    | type '(' ID ')' '(' params ')'
+      {
+        std::reverse($6->begin(), $6->end());
+        $$ = new FunctionDeclaration($1, $3, $6);
+      }
+    | VARARGS
+      {
+        $$ = new VarDeclaration(new Type(NULL), "...");
+      }
+    ;
+
+type
+    : type_qualifiers
+      {
+        std::reverse($1->begin(), $1->end());
+        $$ = new Type($1);
+      }
+    ;
+
+type_qualifiers
+    : type_qualifier
+     {
+        $$ = new std::vector<Type::Qualifier *>;
+        $$->push_back($1);
+     }
+    | type_qualifier type_qualifiers
+     {
+        $$ = $2;
+        $$->push_back($1);
+     }
+    ;
+
+opt_id
+    : /* EMPTY */             { $$ = ""; }
+    |
+     ID                       { $$ = $1; }
+    ;
+
+expr
+    : ID                      { $$ = Expression::atom(Expression::Type::UNKOWN, $1); }
+    | VALUE                   { $$ = Expression::atom(Expression::Type::UNKOWN, $1); }
+    | INTEGRAL_VALUE          { $$ = Expression::atom(Expression::integralType($1), $1); }
+    | '(' expr ')'            { $$ = Expression::parenthesize($2); }
+    | ID '[' expr ']' %prec ARRAY_SUBSCRIPT {
+                                $$ = Expression::arraySubscript($1, $3);
+                              }
+    | ID '(' args ')' %prec FUNCTION_CALL {
+                                std::reverse($3->begin(), $3->end());
+                                $$ = Expression::functionCall($1, $3);
+                              }
+    | expr '?' expr ':' expr  { $$ = Expression::ternary($1, $3, $5); }
+    | expr '+' expr           { $$ = Expression::binary($1, "+", $3); }
+    | expr '-' expr           { $$ = Expression::binary($1, "-", $3); }
+    | expr '/' expr           { $$ = Expression::binary($1, "/", $3); }
+    | expr '*' expr           { $$ = Expression::binary($1, "*", $3); }
+    | expr '%' expr           { $$ = Expression::binary($1, "%%", $3); }
+    | expr '&' expr           { $$ = Expression::binary($1, "&", $3); }
+    | expr '|' expr           { $$ = Expression::binary($1, "|", $3); }
+    | expr '^' expr           { $$ = Expression::binary($1, "^", $3); }
+    | expr LSHIFT expr        { $$ = Expression::binary($1, "<<", $3); }
+    | expr RSHIFT expr        { $$ = Expression::binary($1, ">>", $3); }
+    | '~' expr                { $$ = Expression::unary("~", $2); }
+    | '-' expr %prec UMINUS   { $$ = Expression::unary("-", $2); }
+    | '+' expr %prec UPLUS    { $$ = Expression::unary("+", $2); }
+    ;
+
+args
+    : /* empty */
+      {
+        $$ = new std::vector<Expression *>;
+      }
+    | expr
+      {
+        $$ = new std::vector<Expression *>;
+        $$->push_back($1);
+      }
+    | expr ',' args
+      {
+        $$ = $3;
+        $$->push_back($1);
+      }
+    ;
+
+type_qualifier
+    : UNSIGNED                { $$ = new Type::Qualifier(Type::Qualifier::UNSIGNED); }
+    | SIGNED                  { $$ = new Type::Qualifier(Type::Qualifier::SIGNED); }
+    | VOID                    { $$ = new Type::Qualifier(Type::Qualifier::VOID); }
+    | '*'                     { $$ = new Type::Qualifier(Type::Qualifier::POINTER); }
+    | CONST                   { $$ = new Type::Qualifier(Type::Qualifier::CONST); }
+    | ID                      { $$ = new Type::Qualifier(Type::Qualifier::ID, $1); }
+    | '<' type '>'            { $$ = new Type::Qualifier(Type::Qualifier::GENERICS, $2); }
+    | ENUM                    { $$ = new Type::Qualifier(Type::Qualifier::ENUM); }
+    | struct_or_union         { $$ = new Type::Qualifier($1); }
+    ;
+
+struct_or_union
+    : STRUCT                  { $$ = android::Type::Qualifier::STRUCT; }
+    | UNION                   { $$ = android::Type::Qualifier::UNION; }
+    ;
+
+opt_array
+    : /* empty */             { $$ = NULL; }
+    | '[' ']'                 { $$ = Expression::atom(Expression::Type::UNKOWN, " "); }
+    | '[' expr ']'            { $$ = $2; }
+    ;
+
+%%
\ No newline at end of file
diff --git a/c2hal/main.cpp b/c2hal/main.cpp
new file mode 100644
index 0000000..d8603f3
--- /dev/null
+++ b/c2hal/main.cpp
@@ -0,0 +1,184 @@
+/*
+ * 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 "AST.h"
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <set>
+#include <map>
+#include <stdio.h>
+#include <string>
+#include <unistd.h>
+#include <vector>
+#include <utils/Errors.h>
+
+using namespace android;
+
+extern status_t parseFile(android::AST *ast);
+
+static void usage(const char *me) {
+    fprintf(stderr,
+            "usage: %s [-g] -o dir -p package (-r interface-root)+ (header-filepath)+\n",
+            me);
+
+    fprintf(stderr, "         -o output path\n");
+    fprintf(stderr, "            (example: ~/android/master)\n");
+    fprintf(stderr, "         -p package\n");
+    fprintf(stderr, "            (example: android.hardware.baz@1.0)\n");
+    fprintf(stderr, "         -g (enable open-gl mode) \n");
+    fprintf(stderr, "         -r package:path root "
+                    "(e.g., android.hardware:hardware/interfaces)\n");
+}
+
+static void addPackageRootToMap(const std::string &val,
+                                std::map<std::string, std::string> &packageRootPaths) {
+    auto index = val.find_first_of(':');
+    CHECK(index != std::string::npos);
+
+    auto package = val.substr(0, index);
+    auto path = val.substr(index + 1);
+
+    packageRootPaths[package] = path;
+}
+
+static bool isPathPrefix(const std::string &prefix, const std::string &base) {
+    if (prefix.size() >= base.size()) {
+        LOG(INFO) << "Not long enough";
+        return false;
+    }
+
+    if (base[prefix.size()] != '.') {
+        LOG(INFO) << "not full";
+        return false;
+    }
+
+    return prefix == base.substr(0, prefix.size());
+}
+
+static void applyPackageRootPath(
+        const std::map<std::string, std::string> &packageRootPaths,
+        const std::string &package,
+        std::string &outputPath) {
+
+    auto index = package.find_first_of('@');
+    CHECK(index != std::string::npos);
+
+    auto packagePath = package.substr(0, index);
+    auto packageVersion = package.substr(index + 1);
+
+    for (auto const& pair : packageRootPaths) {
+        const std::string& rootPackage = pair.first;
+        const std::string& rootPath = pair.second;
+
+        if (isPathPrefix(rootPackage, packagePath)) {
+
+            packagePath = packagePath.substr(rootPackage.size() + 1);
+            std::replace(packagePath.begin(), packagePath.end(), '.', '/');
+            packagePath += '/' + packageVersion;
+
+            if (outputPath.empty()) {
+                outputPath = rootPath;
+            }
+
+            outputPath += '/' + packagePath + '/';
+            return;
+        }
+    }
+
+    CHECK(false) << "No package root path provided for package: " << package;
+}
+
+int main(int argc, char **argv) {
+    const char *me = argv[0];
+
+    std::string outputDir;
+    std::string package;
+    std::map<std::string, std::string> packageRootPaths;
+    bool isOpenGl = false;
+
+    int res;
+    while ((res = getopt(argc, argv, "gho:p:r:")) >= 0) {
+        switch (res) {
+            case 'o': {
+                outputDir = optarg;
+                break;
+            }
+            case 'p': {
+                package = optarg;
+                break;
+            }
+            case 'g': {
+                isOpenGl = true;
+                break;
+            }
+            case 'r':
+            {
+                addPackageRootToMap(optarg, packageRootPaths);
+                break;
+            }
+            case 'h':
+            default:
+            {
+                LOG(INFO) << "UNKOWN ARGUMENT: " << optarg;
+                usage(me);
+                exit(1);
+                break;
+            }
+        }
+    }
+
+    // if no arguments are provided, show usage instead of specific errors
+    if (optind == 1) {
+        usage(me);
+        exit(0);
+    }
+
+    applyPackageRootPath(packageRootPaths, package, outputDir);
+
+    if (package.empty()) {
+        LOG(WARNING) << "You must provide a package.";
+        usage(me);
+        exit(0);
+    }
+
+    if (optind == argc) {
+        LOG(WARNING) << "You must provide a header-filepath.";
+        usage(me);
+        exit(0);
+    }
+
+    for(int i = optind; i < argc; i++) {
+        std::string path = argv[i];
+
+        LOG(INFO) << "Processing " << path;
+
+        AST ast(path, outputDir, package, isOpenGl);
+
+        int res = parseFile(&ast);
+
+        if (res != 0) {
+            LOG(ERROR) << "Could not parse: " << res;
+            exit(1);
+        }
+
+        ast.processContents();
+
+        ast.generateCode();
+    }
+
+    return 0;
+}
diff --git a/c2hal/test/build_all.py b/c2hal/test/build_all.py
new file mode 100644
index 0000000..b9faf0b
--- /dev/null
+++ b/c2hal/test/build_all.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+
+
+from os import listdir
+from os.path import isfile, join as path_join
+from subprocess import call
+import argparse
+
+def main():
+    """this python program tries to build all hardware interfaces from a directory"""
+
+    args = parseArgs()
+
+    path = args.path
+    is_open_gl = args.g
+
+    success, failure = genFiles(path, is_open_gl)
+
+    print("Success: ", ", ".join(success))
+    print("Failure: ", ", ".join(failure))
+
+    ratio = len(success) / (len(success) + len(failure))
+
+    print("%% success = %.2f" % (100 * ratio))
+
+def parseArgs():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("path", help="location of headers to parse", type=str)
+    parser.add_argument("-g", help="enable opengl specific parsing", action="store_true")
+
+    return parser.parse_args()
+
+def genFiles(path, is_open_gl):
+    success = []
+    failure = []
+
+    for header in sorted(headers(path)):
+        fname = header[:-2]
+
+        command = ["c2hal",
+                   "-r", "android.hardware:hardware/interfaces",
+                   "-p", "android.hardware." + fname + "@1.0"]
+
+        if is_open_gl:
+            command += ["-g"]
+
+        command += [path_join(path, header)]
+
+        res = call(command)
+
+        if res == 0:
+            success += [header]
+        else:
+            failure += [header]
+
+    return success, failure
+
+def headers(path):
+    """all .h files in a directory"""
+    for item in listdir(path):
+        if not isfile(path_join(path, item)):
+            continue
+
+        if not item.endswith(".h"):
+            continue
+
+        yield item
+
+
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/c2hal/test/simple.h b/c2hal/test/simple.h
new file mode 100644
index 0000000..7f5f69c
--- /dev/null
+++ b/c2hal/test/simple.h
@@ -0,0 +1,84 @@
+/*
+ * 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 SIMPLE_H
+#define SIMPLE_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <cutils/native_handle.h>
+
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+#define FORGROUND_COLOR "#133742"
+#define ACTOR_COLOR "#424242"
+
+/* Simple example */
+typedef struct simple_t {
+    /**
+     * Common methods of the simple device.
+     */
+    struct hw_device_t common;
+
+    /* resolution of the framebuffer's display panel in pixel per inch*/
+    const float     xdpi;
+    const float     ydpi;
+
+    /* framebuffer's display panel refresh rate in frames per second */
+    const float     fps;
+
+    int (*setSwapInterval)(struct simple_t* window,
+            int interval);
+
+    /*
+     * This hook is OPTIONAL.
+     */
+    int (*setUpdateRect)(struct simple_t* window,
+            int left, int top, int width, int height);
+
+} simple_t;
+
+/* Holds pixel coordinates */
+typedef struct {
+    int px;
+    int py;
+
+    /*
+     * If non NULL it will be caused by SurfaceFlinger on dumpsys
+     */
+    void (*dump)(struct simple_t* dev, char *buff, int buff_len);
+
+} simple_location_t;
+
+/** convenience API for coloring */
+
+static inline int showColor(const struct hw_module_t* module,
+        struct simple_t** device) {
+    return module->methods->open(module,
+            FORGROUND_COLOR, (struct simple_t**)device);
+}
+
+static inline int hideColor(struct simple_t* device) {
+    return device->common.close(&device->common);
+}
+
+__END_DECLS
+
+#endif  // SIMPLE_H
diff --git a/c2hal/test/test.h b/c2hal/test/test.h
new file mode 100644
index 0000000..8746cfa
--- /dev/null
+++ b/c2hal/test/test.h
@@ -0,0 +1,337 @@
+/*
+ * 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 ANDROID_FB_INTERFACE_H
+#define ANDROID_FB_INTERFACE_H
+
+
+#include <onelib>
+#include <there/somelib.h>
+#include "mylib.h"
+
+__BEGIN_DECLS
+
+// comments
+
+#define MY_DEFINE 1 \
+                  + 1
+#define META(thing1, thing2) thing1 + thing2
+#define VERSION HARDWARE_MODULE_API_VERSION(0, 1)
+#define ONE 1 /* got to
+                 get rid of magic numbers */
+
+/* test */
+/** test */
+/* test **/
+/* test / ** ** / test */
+/* test //// ***** test /****/
+
+#define a 1l
+#define b 1l + 2ll
+#define c 1ul + 1l
+#define d 2 + 1l
+#define e 3 + 1ll
+#define f 4 + 3ul
+#define g 1l + 3
+#define h 32u
+#define i 64ull
+#define j 2 + a
+#define k 1u
+#define l k + 1l
+
+/*****************************************************************************/
+typedef enum {
+    A = 47,
+    /* B is a very important value */
+    B,
+    C = 1 + test(19) + test2[21],
+    D = 1 ? 1 : 2
+} onehere;
+
+inline std::string to_string(T value) { return to_string(static_cast<E>(value)); }
+
+const res_t RESULT_ACCESS_DENIED = ~2 | -1;
+const res_t RESULT_INVALID_PARAMETER = 54;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static void fun1() { }
+
+namespace MyNamespace {
+    static void fun2() { }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+static void fun3() { test; }
+static void fun4() { test; }
+
+#undef ONE
+
+/*****************************************************************************/
+typedef void (*no_arg_fun)(void);
+
+typedef int (*other_fun)(int j);
+
+typedef void (*alarm_cb)(void *data);
+
+typedef void (*special_types)(const native_handle_t* a, int b);
+
+typedef foo_t bar_t;
+
+struct baz_t;
+
+typedef pthread_t (* fun_with_funs)(void (*my_fun)(void *), void* arg);
+
+int (*global_fun_1)(struct framebuffer_device_t* dev, int enable);
+int (*global_fun_2)(struct framebuffer_device_t* dev, int enable);
+
+typedef struct framebuffer_device_t {
+    /**
+     * Common methods of the framebuffer device.
+     */
+    struct hw_device_t common;
+
+    typedef enum another_here {
+        A = 3 | 4,
+        B,
+        C = 4
+    } another_here;
+
+    /* anon struct */
+    struct {
+        float b;
+    };
+
+    struct not_type_defd {
+        double latitude[];
+        double halfLongitude;
+    };
+
+    /* flags describing some attributes of the framebuffer */
+    const uint32_t  flags;
+
+    /* dimensions of the framebuffer in pixels */
+    const uint32_t  width;
+    const uint32_t  height;
+
+    /* frambuffer stride in pixels */
+    const int       stride;
+
+    /* framebuffer pixel format */
+    const int       format;
+
+    /* resolution of the framebuffer's display panel in pixel per inch*/
+    const float     xdpi;
+    const float     ydpi;
+
+    /* framebuffer's display panel refresh rate in frames per second */
+    const float     fps;
+
+    /* min swap interval supported by this framebuffer */
+    const int       minSwapInterval;
+
+    /* max swap interval supported by this framebuffer */
+    const int       maxSwapInterval;
+
+    /* Number of framebuffers supported*/
+    const int       numFramebuffers;
+
+    int reserved[7];
+
+    /*
+     * requests a specific swap-interval (same definition than EGL)
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int (*setSwapInterval)(struct framebuffer_device_t* window,
+            int interval);
+
+    /*
+     * This hook is OPTIONAL.
+     *
+     * It is non NULL If the framebuffer driver supports "update-on-demand"
+     * and the given rectangle is the area of the screen that gets
+     * updated during (*post)().
+     *
+     * This is useful on devices that are able to DMA only a portion of
+     * the screen to the display panel, upon demand -- as opposed to
+     * constantly refreshing the panel 60 times per second, for instance.
+     *
+     * Only the area defined by this rectangle is guaranteed to be valid, that
+     * is, the driver is not allowed to post anything outside of this
+     * rectangle.
+     *
+     * The rectangle evaluated during (*post)() and specifies which area
+     * of the buffer passed in (*post)() shall to be posted.
+     *
+     * return -EINVAL if width or height <=0, or if left or top < 0
+     */
+    int (*setUpdateRect)(struct framebuffer_device_t* window,
+            int left, int top, int width, int height);
+
+    /*
+     * Post <buffer> to the display (display it on the screen)
+     * The buffer must have been allocated with the
+     *   GRALLOC_USAGE_HW_FB usage flag.
+     * buffer must be the same width and height as the display and must NOT
+     * be locked.
+     *
+     * The buffer is shown during the next VSYNC.
+     *
+     * If the same buffer is posted again (possibly after some other buffer),
+     * post() will block until the the first post is completed.
+     *
+     * Internally, post() is expected to lock the buffer so that a
+     * subsequent call to gralloc_module_t::(*lock)() with USAGE_RENDER or
+     * USAGE_*_WRITE will block until it is safe; that is typically once this
+     * buffer is shown and another buffer has been posted.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
+
+
+    /*
+     * The (*compositionComplete)() method must be called after the
+     * compositor has finished issuing GL commands for client buffers.
+     */
+
+    int (*compositionComplete)(struct framebuffer_device_t* dev);
+
+    /*
+     * This hook is OPTIONAL.
+     *
+     * If non NULL it will be caused by SurfaceFlinger on dumpsys
+     */
+    void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);
+
+    /*
+     * (*enableScreen)() is used to either blank (enable=0) or
+     * unblank (enable=1) the screen this framebuffer is attached to.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int (*enableScreen)(struct framebuffer_device_t* dev, int enable);
+
+    void* reserved_proc[6];
+
+} framebuffer_device_t;
+
+typedef int context_hub_callback(uint32_t hub_id, const struct hub_message_t *rxed_msg, void *cookie);
+
+typedef struct my_other_t {
+
+    int (*store_meta_data_in_buffers)(struct camera_device *, int enable);
+
+    typedef void (*scan_result_callback)(bt_bdaddr_t* bda, int rssi, vector<uint8_t> adv_data);
+
+    pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+    int (*p1)(struct framebuffer_device_t* dev);
+
+    void (*p2)(struct framebuffer_device_t* dev, char *buff, int buff_len);
+
+    int (*p3)(struct framebuffer_device_t* dev, int enable);
+
+
+    int (*get_supported_activities_list)(struct activity_recognition_module* module,
+            char const* const* *activity_list);
+
+    int (*read_energy_info)();
+    void (*reserved_procs[16 - 4])(void);
+
+} my_other_t;
+
+#define another 4
+
+typedef struct {
+    /** set to sizeof(GpsCallbacks_v1) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+} __attribute__((packed)) GpsCallbacks_v1;
+
+typedef struct one_name {
+    float a;
+} another_name;
+
+typedef struct this_t {
+    int hello;
+} this_t;
+
+typedef union that_t {
+    float a;
+    float c;
+} that_t;
+
+/**
+ * return the frame size (number of bytes per sample) of an output stream.
+ */
+static inline size_t audio_stream_out_frame_size(const struct audio_stream_out *s)
+{
+    size_t chan_samp_sz;
+    audio_format_t format = s->common.get_format(&s->common);
+
+    if (audio_has_proportional_frames(format)) {
+        chan_samp_sz = audio_bytes_per_sample(format);
+        return audio_channel_count_from_out_mask(s->common.get_channels(&s->common)) * chan_samp_sz;
+    }
+
+    return sizeof(int8_t);
+}
+
+/* effective and commanding */
+enum effect_command_e {
+   EFFECT_CMD_INIT,                 // initialize effect engine
+   EFFECT_CMD_SET_CONFIG,           // configure effect engine (see effect_config_t)
+   EFFECT_CMD_RESET,                // reset effect engine
+   EFFECT_CMD_ENABLE,               // enable effect process
+   EFFECT_CMD_DISABLE,              // disable effect process
+   EFFECT_CMD_SET_PARAM,            // set parameter immediately (see effect_param_t)
+   EFFECT_CMD_SET_PARAM_DEFERRED,   // set parameter deferred
+   EFFECT_CMD_SET_PARAM_COMMIT,     // commit previous set parameter deferred
+   EFFECT_CMD_GET_PARAM,            // get parameter
+   EFFECT_CMD_SET_DEVICE,           // set audio device (see audio.h, audio_devices_t)
+   EFFECT_CMD_SET_VOLUME,           // set volume
+   EFFECT_CMD_SET_AUDIO_MODE,       // set the audio mode (normal, ring, ...)
+   EFFECT_CMD_SET_CONFIG_REVERSE,   // configure effect engine reverse stream(see effect_config_t)
+   EFFECT_CMD_SET_INPUT_DEVICE,     // set capture device (see audio.h, audio_devices_t)
+   EFFECT_CMD_GET_CONFIG,           // read effect engine configuration
+   EFFECT_CMD_GET_CONFIG_REVERSE,   // read configure effect engine reverse stream configuration
+   EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,// get all supported configurations for a feature.
+   EFFECT_CMD_GET_FEATURE_CONFIG,   // get current feature configuration
+   EFFECT_CMD_SET_FEATURE_CONFIG,   // set current feature configuration
+   EFFECT_CMD_SET_AUDIO_SOURCE,     // set the audio source (see audio.h, audio_source_t)
+   EFFECT_CMD_OFFLOAD,              // set if effect thread is an offload one,
+                                    // send the ioHandle of the effect thread
+   EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
+};
+
+__END_DECLS
+
+#endif
\ No newline at end of file
diff --git a/generateCpp.cpp b/generateCpp.cpp
index e472245..57ed349 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -49,6 +49,10 @@
     }
 
     if (err == OK) {
+        err = generateHwBinderHeader(outputPath);
+    }
+
+    if (err == OK) {
         err = generateProxyHeader(outputPath);
     }
 
@@ -158,10 +162,9 @@
     }
 
     out << "#include <hidl/HidlSupport.h>\n";
+    out << "#include <hidl/IServiceManager.h>\n";
 
     if (isInterface) {
-        out << "#include <hwbinder/IBinder.h>\n";
-        out << "#include <hwbinder/IInterface.h>\n";
         out << "#include <hwbinder/Status.h>\n";
     }
 
@@ -170,28 +173,27 @@
     enterLeaveNamespace(out, true /* enter */);
     out << "\n";
 
+    // cut off the leading 'I'.
+    const std::string baseName = ifaceName.substr(1);
+
     if (isInterface) {
         out << "struct "
-            << ifaceName
-            << " : public ";
+            << ifaceName;
 
         const Interface *iface = mRootScope->getInterface();
         const Interface *superType = iface->superType();
 
-        if (superType != NULL) {
-            out << superType->fullName();
+        if (superType == NULL) {
+            out << " : virtual public RefBase";
         } else {
-            out << "::android::hardware::IInterface";
+            out << " : public "
+                << superType->fullName();
         }
 
         out << " {\n";
 
         out.indent();
 
-        // cut off the leading 'I'.
-        const std::string baseName = ifaceName.substr(1);
-
-        out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
     }
 
     status_t err = emitTypeDeclarations(out);
@@ -204,33 +206,7 @@
         const Interface *iface = mRootScope->getInterface();
         const Interface *superType = iface->superType();
 
-        out << "enum Call {\n";
-        out.indent();
-
-        bool first = true;
-        for (const auto &method : iface->methods()) {
-            out << upcase(method->name());
-
-            if (first) {
-                out << " = ";
-                if (superType != NULL) {
-                    out << superType->fullName()
-                        << "::Call::CallCount";
-                } else {
-                    out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
-                }
-
-                first = false;
-            }
-
-            out << ",\n";
-        }
-
-        out << "CallCount\n";
-
-        out.unindent();
-        out << "};\n\n";
-
+        out << "virtual bool isRemote() const { return false; } \n\n";
         bool haveCallbacks = false;
         for (const auto &method : iface->methods()) {
             const bool returnsValue = !method->results().empty();
@@ -284,6 +260,8 @@
 
             out << ") = 0;\n";
         }
+
+        out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
     }
 
     if (isInterface) {
@@ -300,12 +278,143 @@
     return OK;
 }
 
+status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
+    std::string ifaceName;
+    if(!AST::isInterface(&ifaceName)) {
+        // types.hal does not get an HwBinder header.
+        return OK;
+    }
+
+    // cut off the leading 'I'.
+    const std::string baseName = ifaceName.substr(1);
+
+    const std::string klassName = "IHw" + baseName;
+
+    std::string path = outputPath;
+    path.append(mCoordinator->convertPackageRootToPath(mPackage));
+    path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
+    path.append(klassName + ".h");
+
+    FILE* file = fopen(path.c_str(), "w");
+
+    if (file == NULL) {
+        return -errno;
+    }
+
+    Formatter out(file);
+
+    const std::string guard = makeHeaderGuard(klassName);
+
+    out << "#ifndef " << guard << "\n";
+    out << "#define " << guard << "\n\n";
+
+    std::vector<std::string> packageComponents;
+    getPackageAndVersionComponents(
+            &packageComponents, false /* cpp_compatible */);
+
+    out << "#include <";
+    for (const auto &component : packageComponents) {
+        out << component << "/";
+    }
+    out << ifaceName << ".h>\n\n";
+
+    for (const auto &item : mImportedNames) {
+        if (item.name() == "types") {
+            continue;
+        }
+
+        out << "#include <";
+
+        std::vector<std::string> components;
+        item.getPackageAndVersionComponents(
+                &components, false /* cpp_compatible */);
+
+        for (const auto &component : components) {
+            out << component << "/";
+        }
+
+        // cut off the leading I
+        const std::string itemBaseName = item.name().substr(1);
+
+        out << "Bn"
+            << itemBaseName
+            << ".h>\n";
+    }
+
+    out << "\n";
+
+    out << "#include <hidl/HidlSupport.h>\n";
+    out << "#include <hwbinder/IBinder.h>\n";
+    out << "#include <hwbinder/IInterface.h>\n";
+    out << "#include <hwbinder/Status.h>\n";
+
+    out << "\n";
+
+    enterLeaveNamespace(out, true /* enter */);
+    out << "\n";
+
+    out << "struct "
+        << klassName
+        << " : public "
+        << ifaceName;
+
+    const Interface *iface = mRootScope->getInterface();
+    const Interface *superType = iface->superType();
+
+    out << ", public ::android::hardware::IInterface";
+
+    out << " {\n";
+
+    out.indent();
+
+    out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
+
+    out << "enum Call {\n";
+    out.indent();
+
+    bool first = true;
+    for (const auto &method : iface->methods()) {
+        out << upcase(method->name());
+
+        if (first) {
+            out << " = ";
+            if (superType != NULL) {
+                out << superType->fqName().cppNamespace()
+                    << "::IHw"
+                    << superType->getBaseName()
+                    << "::Call::CallCount";
+            } else {
+                out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
+            }
+
+            first = false;
+        }
+
+        out << ",\n";
+    }
+
+    out << "CallCount\n";
+
+    out.unindent();
+    out << "};\n\n";
+
+    out.unindent();
+
+    out << "};\n\n";
+
+    enterLeaveNamespace(out, false /* enter */);
+
+    out << "\n#endif  // " << guard << "\n";
+
+    return OK;
+}
+
 status_t AST::emitTypeDeclarations(Formatter &out) const {
     return mRootScope->emitTypeDeclarations(out);
 }
 
 status_t AST::generateHeaderMethodSignatures(
-        Formatter &out, bool abstract) const {
+        Formatter &out, bool stub) const {
     const Interface *iface = mRootScope->getInterface();
 
     std::vector<const Interface *> chain;
@@ -322,6 +431,9 @@
             << " follow.\n";
 
         for (const auto &method : superInterface->methods()) {
+            if (stub) {
+                out << "inline ";
+            }
             const bool returnsValue = !method->results().empty();
 
             const TypedVar *elidedReturn = method->canElideCallback();
@@ -346,7 +458,33 @@
             }
 
             out << ") ";
-            out << (abstract ? "= 0" : "override");
+            if (stub) {
+                out << " {\n";
+                out.indent();
+                out << "return mImpl->"
+                    << method->name()
+                    << "(";
+                bool first = true;
+                for (const auto &arg : method->args()) {
+                    if (!first) {
+                        out << ", ";
+                    }
+                    first = false;
+                    out << arg->name();
+                }
+                if (returnsValue && elidedReturn == nullptr) {
+                    if (!method->args().empty()) {
+                        out << ", ";
+                    }
+
+                    out << "_hidl_cb";
+                }
+                out << ");\n";
+                out.unindent();
+                out << "}";
+            } else {
+                out << "override";
+            }
             out << ";\n";
         }
 
@@ -365,12 +503,12 @@
 
     // cut off the leading 'I'.
     const std::string baseName = ifaceName.substr(1);
+    const std::string klassName = "Bn" + baseName;
 
     std::string path = outputPath;
     path.append(mCoordinator->convertPackageRootToPath(mPackage));
     path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
-    path.append("Bn");
-    path.append(baseName);
+    path.append(klassName);
     path.append(".h");
 
     CHECK(Coordinator::MakeParentHierarchy(path));
@@ -382,7 +520,7 @@
 
     Formatter out(file);
 
-    const std::string guard = makeHeaderGuard("Bn" + baseName);
+    const std::string guard = makeHeaderGuard(klassName);
 
     out << "#ifndef " << guard << "\n";
     out << "#define " << guard << "\n\n";
@@ -395,7 +533,7 @@
     for (const auto &component : packageComponents) {
         out << component << "/";
     }
-    out << ifaceName << ".h>\n\n";
+    out << "IHw" << baseName << ".h>\n\n";
 
     enterLeaveNamespace(out, true /* enter */);
     out << "\n";
@@ -403,12 +541,15 @@
     out << "struct "
         << "Bn"
         << baseName
-        << " : public ::android::hardware::BnInterface<"
-        << ifaceName
+        << " : public ::android::hardware::BnInterface<I"
+        << baseName << ", IHw" << baseName
         << "> {\n";
 
     out.indent();
-
+    out << "explicit Bn"
+        << baseName
+        << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
+        << "\n\n";
     out << "::android::status_t onTransact(\n";
     out.indent();
     out.indent();
@@ -420,8 +561,7 @@
     out.unindent();
     out.unindent();
 
-    generateHeaderMethodSignatures(out, true); // = 0
-
+    generateHeaderMethodSignatures(out, true); // stub
     out.unindent();
 
     out << "};\n\n";
@@ -472,7 +612,7 @@
     for (const auto &component : packageComponents) {
         out << component << "/";
     }
-    out << ifaceName << ".h>\n\n";
+    out << "IHw" << baseName << ".h>\n\n";
 
     enterLeaveNamespace(out, true /* enter */);
     out << "\n";
@@ -480,8 +620,8 @@
     out << "struct "
         << "Bp"
         << baseName
-        << " : public ::android::hardware::BpInterface<"
-        << ifaceName
+        << " : public ::android::hardware::BpInterface<IHw"
+        << baseName
         << "> {\n";
 
     out.indent();
@@ -491,7 +631,9 @@
         << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
         << "\n\n";
 
-    generateHeaderMethodSignatures(out, false); // override
+    out << "virtual bool isRemote() const { return true; } \n\n";
+
+    generateHeaderMethodSignatures(out, false); // proxy
 
     out.unindent();
 
@@ -570,6 +712,10 @@
         err = generateStubSource(out, baseName);
     }
 
+    if (err == OK && isInterface) {
+        out << "IMPLEMENT_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
+    }
+
     enterLeaveNamespace(out, false /* enter */);
 
     return err;
@@ -631,7 +777,7 @@
     out.indent();
 
     out << ": BpInterface"
-        << "<I"
+        << "<IHw"
         << baseName
         << ">(_hidl_impl) {\n";
 
@@ -684,12 +830,13 @@
             out << "::android::hardware::Parcel _hidl_reply;\n";
             out << "::android::status_t _hidl_err;\n";
             out << "::android::hardware::Status _hidl_status;\n\n";
-
             declareCppReaderLocals(out, method->results());
 
             out << "_hidl_err = _hidl_data.writeInterfaceToken("
-                << superInterface->fullName()
-                << "::getInterfaceDescriptor());\n";
+                << superInterface->fqName().cppNamespace()
+                << "::IHw"
+                << superInterface->getBaseName()
+                << "::descriptor);\n";
 
             out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
 
@@ -703,9 +850,11 @@
                         Type::ErrorMode_Goto);
             }
 
-            out << "_hidl_err = remote()->transact(I"
-                      << baseName
-                      << "::"
+            out << "_hidl_err = remote()->transact("
+                      << superInterface->fqName().cppNamespace()
+                      << "::IHw"
+                      << superInterface->getBaseName()
+                      << "::Call::"
                       << upcase(method->name())
                       << ", _hidl_data, &_hidl_reply";
             if (method->isOneway()) {
@@ -798,6 +947,25 @@
 
     const std::string klassName = "Bn" + baseName;
 
+    out << klassName
+        << "::"
+        << klassName
+        << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
+
+    out.indent();
+    out.indent();
+
+    out << ": BnInterface"
+        << "<I"
+        << baseName
+        << ", IHw"
+        << baseName
+        << ">(_hidl_impl) {\n";
+
+    out.unindent();
+    out.unindent();
+    out << "}\n\n";
+
     out << "::android::status_t " << klassName << "::onTransact(\n";
 
     out.indent();
@@ -812,7 +980,6 @@
     out.unindent();
 
     out << "::android::status_t _hidl_err = ::android::OK;\n\n";
-
     out << "switch (_hidl_code) {\n";
     out.indent();
 
@@ -829,7 +996,9 @@
 
         for (const auto &method : superInterface->methods()) {
             out << "case "
-                << superInterface->fullName()
+                << superInterface->fqName().cppNamespace()
+                << "::IHw"
+                << superInterface->getBaseName()
                 << "::Call::"
                 << upcase(method->name())
                 << ":\n{\n";
@@ -852,7 +1021,7 @@
     out.indent();
 
     out << "return ::android::hardware::BnInterface<I"
-        << baseName
+        << baseName << ", IHw" << baseName
         << ">::onTransact(\n";
 
     out.indent();
@@ -898,8 +1067,10 @@
 status_t AST::generateStubSourceForMethod(
         Formatter &out, const Interface *iface, const Method *method) const {
     out << "if (!_hidl_data.enforceInterface("
-        << iface->fullName()
-        << "::getInterfaceDescriptor())) {\n";
+        << iface->fqName().cppNamespace()
+        << "::IHw"
+        << iface->getBaseName()
+        << "::descriptor)) {\n";
 
     out.indent();
     out << "_hidl_err = ::android::BAD_TYPE;\n";
diff --git a/generateJava.cpp b/generateJava.cpp
index f10ae92..a3c4761 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -51,7 +51,8 @@
     arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
 }
 
-status_t AST::generateJavaTypes(const std::string &outputPath) const {
+status_t AST::generateJavaTypes(
+        const std::string &outputPath, const char *limitToType) const {
     // Splits types.hal up into one java file per declared type.
 
     for (size_t i = 0; i < mRootScope->countTypes(); ++i) {
@@ -62,6 +63,10 @@
             continue;
         }
 
+        if ((limitToType != nullptr) && typeName != limitToType) {
+            continue;
+        }
+
         std::string path = outputPath;
         path.append(mCoordinator->convertPackageRootToPath(mPackage));
         path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
@@ -99,14 +104,9 @@
     return OK;
 }
 
-status_t AST::generateJava(const std::string &outputPath) const {
-    std::string ifaceName;
-    if (!AST::isInterface(&ifaceName)) {
-        return generateJavaTypes(outputPath);
-    }
-
-    const Interface *iface = mRootScope->getInterface();
-    if (!iface->isJavaCompatible()) {
+status_t AST::generateJava(
+        const std::string &outputPath, const char *limitToType) const {
+    if (!isJavaCompatible()) {
         fprintf(stderr,
                 "ERROR: This interface is not Java compatible. The Java backend"
                 " does NOT support union types or native handles.\n");
@@ -114,6 +114,13 @@
         return UNKNOWN_ERROR;
     }
 
+    std::string ifaceName;
+    if (!AST::isInterface(&ifaceName)) {
+        return generateJavaTypes(outputPath, limitToType);
+    }
+
+    const Interface *iface = mRootScope->getInterface();
+
     // cut off the leading 'I'.
     const std::string baseName = ifaceName.substr(1);
 
diff --git a/generateVts.cpp b/generateVts.cpp
index 0c3ba93..4f3585f 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -107,22 +107,6 @@
     Formatter out(file);
 
     out << "component_class: HAL_HIDL\n";
-
-    // Get the component_type for interface from annotation.
-    if (isInterface) {
-        const Interface *iface = mRootScope->getInterface();
-        Annotation *annotation = iface->annotations().valueFor("hal_type");
-        if (annotation != NULL) {
-            std::vector<std::string> * values = annotation->params().valueFor(
-                    "type");
-            if (values != NULL) {
-                out << "component_type: "
-                    << removeQuotes(values->at(0))
-                    << "\n";
-            }
-        }
-    }
-
     out << "component_type_version: " << mPackage.version().substr(1) << "\n";
     out << "component_name: \""
         << (isInterface ? ifaceName : "types")
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 4da811d..698f69d 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -352,8 +352,8 @@
     ;
 
 const_expr
-    : INTEGER                   { $$ = new ConstantExpression($1); }
-    | IDENTIFIER                { $$ = new ConstantExpression($1); }
+    : INTEGER                   { $$ = new ConstantExpression($1, ConstantExpression::kConstExprLiteral); }
+    | IDENTIFIER                { $$ = new ConstantExpression($1, ConstantExpression::kConstExprUnknown); }
     | const_expr '?' const_expr ':' const_expr
       {
         $$ = new ConstantExpression($1, $3, $5);
@@ -570,7 +570,7 @@
 
 enum_value
     : IDENTIFIER { $$ = new EnumValue($1); }
-    | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3->value()); }
+    | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3); }
     ;
 
 enum_values
diff --git a/main.cpp b/main.cpp
index 7fb048e..e7d959a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -18,6 +18,7 @@
 #include "Coordinator.h"
 #include "Formatter.h"
 #include "FQName.h"
+#include "Scope.h"
 
 #include <android-base/logging.h>
 #include <set>
@@ -36,7 +37,7 @@
         PASS_PACKAGE,
         PASS_FULL
     };
-    ValRes (*validate)(const FQName &);
+    ValRes (*validate)(const FQName &, const std::string &language);
     status_t (*generate)(const FQName &fqName,
                          const char *hidl_gen,
                          Coordinator *coordinator,
@@ -51,7 +52,19 @@
         const std::string &lang) {
     CHECK(fqName.isFullyQualified());
 
-    AST *ast = coordinator->parse(fqName);
+    AST *ast;
+    const char *limitToType = nullptr;
+
+    if (fqName.name().find("types.") == 0) {
+        CHECK(lang == "java");  // Already verified in validate().
+
+        limitToType = fqName.name().c_str() + strlen("types.");
+
+        FQName typesName(fqName.package(), fqName.version(), "types");
+        ast = coordinator->parse(typesName);
+    } else {
+        ast = coordinator->parse(fqName);
+    }
 
     if (ast == NULL) {
         fprintf(stderr,
@@ -65,7 +78,7 @@
         return ast->generateCpp(outputDir);
     }
     if (lang == "java") {
-        return ast->generateJava(outputDir);
+        return ast->generateJava(outputDir, limitToType);
     }
     if (lang == "vts") {
         return ast->generateVts(outputDir);
@@ -109,6 +122,110 @@
     return packageFQName.string();
 }
 
+static void generateMakefileSectionForLanguageAndType(
+        Formatter &out,
+        Coordinator *coordinator,
+        const FQName &packageFQName,
+        const FQName &fqName,
+        const char *typeName,
+        bool forJava) {
+    out << "\n"
+        << "\n#"
+        << "\n# Build " << fqName.name() << ".hal";
+
+    if (forJava && typeName != nullptr) {
+        out << " (" << typeName << ")";
+    }
+
+    out << "\n#"
+        << "\nGEN := $(intermediates)/"
+        << coordinator->convertPackageRootToPath(packageFQName)
+        << coordinator->getPackagePath(packageFQName, true /* relative */);
+    if (!forJava) {
+        CHECK(typeName == nullptr);
+
+        if (fqName.name() == "types") {
+            out << "types.cpp";
+        } else {
+            out << fqName.name().substr(1) << "All.cpp";
+        }
+    } else if (typeName == nullptr) {
+        out << fqName.name() << ".java";
+    } else {
+        out << typeName << ".java";
+    }
+
+    out << "\n$(GEN): $(HIDL)";
+    out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
+    out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
+        << fqName.name() << ".hal";
+    out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
+        << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
+    out.indent();
+    out.indent();
+    out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
+        << "\n-L"
+        << (forJava ? "java" : "c++")
+        << " -r"
+        << coordinator->getPackageRoot(packageFQName) << ":"
+        << coordinator->getPackageRootPath(packageFQName) << " \\\n";
+
+    out << packageFQName.string()
+        << "::"
+        << fqName.name();
+
+    if (forJava && typeName != nullptr) {
+        out << "." << typeName;
+    }
+
+    out << "\n";
+
+    out.unindent();
+    out.unindent();
+
+    out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
+    out << "\n\t$(transform-generated-source)";
+    out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
+}
+
+static void generateMakefileSectionForLanguage(
+        Formatter &out,
+        Coordinator *coordinator,
+        const FQName &packageFQName,
+        const std::vector<FQName> &packageInterfaces,
+        AST *typesAST,
+        bool forJava) {
+    for (const auto &fqName : packageInterfaces) {
+        if (forJava && fqName.name() == "types") {
+            CHECK(typesAST != nullptr);
+
+            Scope *rootScope = typesAST->scope();
+            for (size_t i = 0; i < rootScope->countTypes(); ++i) {
+                std::string typeName;
+                rootScope->typeAt(i, &typeName);
+
+                generateMakefileSectionForLanguageAndType(
+                        out,
+                        coordinator,
+                        packageFQName,
+                        fqName,
+                        typeName.c_str(),
+                        forJava);
+            }
+
+            continue;
+        }
+
+        generateMakefileSectionForLanguageAndType(
+                out,
+                coordinator,
+                packageFQName,
+                fqName,
+                nullptr /* typeName */,
+                forJava);
+    }
+}
+
 static status_t generateMakefileForPackage(
         const FQName &packageFQName,
         const char *hidl_gen,
@@ -130,6 +247,9 @@
     }
 
     std::set<FQName> importedPackages;
+    bool packageIsJavaCompatible = true;
+    AST *typesAST = nullptr;
+
     for (const auto &fqName : packageInterfaces) {
         AST *ast = coordinator->parse(fqName);
 
@@ -141,6 +261,14 @@
             return UNKNOWN_ERROR;
         }
 
+        if (packageIsJavaCompatible && !ast->isJavaCompatible()) {
+            packageIsJavaCompatible = false;
+        }
+
+        if (fqName.name() == "types") {
+            typesAST = ast;
+        }
+
         ast->getImportedPackages(&importedPackages);
     }
 
@@ -170,44 +298,13 @@
         << "HIDL := $(HOST_OUT_EXECUTABLES)/"
         << hidl_gen << "$(HOST_EXECUTABLE_SUFFIX)";
 
-    for (const auto &fqName : packageInterfaces) {
-
-        out << "\n"
-            << "\n#"
-            << "\n# Build " << fqName.name() << ".hal"
-            << "\n#";
-        out << "\nGEN := $(intermediates)/"
-            << coordinator->convertPackageRootToPath(packageFQName)
-            << coordinator->getPackagePath(packageFQName, true /* relative */);
-        if (fqName.name() == "types") {
-            out << "types.cpp";
-        } else {
-            out << fqName.name().substr(1) << "All.cpp";
-        }
-
-        out << "\n$(GEN): $(HIDL)";
-        out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
-        out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
-            << fqName.name() << ".hal";
-        out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
-            << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
-        out.indent();
-        out.indent();
-        out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
-            << "\n-Lc++ -r"
-            << coordinator->getPackageRoot(packageFQName) << ":"
-            << coordinator->getPackageRootPath(packageFQName) << "\\";
-        out << "\n"
-            << packageFQName.string()
-            << "::$(patsubst %.hal,%,$(notdir $(PRIVATE_DEPS)))"
-            << "\n";
-        out.unindent();
-        out.unindent();
-
-        out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
-        out << "\n\t$(transform-generated-source)";
-        out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
-    }
+    generateMakefileSectionForLanguage(
+            out,
+            coordinator,
+            packageFQName,
+            packageInterfaces,
+            typesAST,
+            false /* forJava */);
 
     out << "\n"
         << "\nLOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)"
@@ -224,18 +321,39 @@
     out.unindent();
     out << "\nLOCAL_MULTILIB := both";
 
-    if (path.find("hardware/interfaces/tests/") != std::string::npos) {
-        out << "\nLOCAL_COMPATIBILITY_SUITE := vts"
-            << "\n-include test/vts/tools/build/Android.packaging_sharedlib.mk";
-        // TODO(yim): b/30589200 remove the above -include line after the
-        // build rule change is merged.
-    }
     out << "\ninclude $(BUILD_SHARED_LIBRARY)\n";
 
+    if (packageIsJavaCompatible) {
+        out << "\n"
+            << "########################################"
+            << "########################################\n\n";
+
+        out << "include $(CLEAR_VARS)\n"
+            << "LOCAL_MODULE := "
+            << libraryName
+            << "-java\n"
+            << "LOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
+            << "intermediates := $(local-generated-sources-dir)\n\n"
+            << "HIDL := $(HOST_OUT_EXECUTABLES)/"
+            << hidl_gen
+            << "$(HOST_EXECUTABLE_SUFFIX)";
+
+        generateMakefileSectionForLanguage(
+                out,
+                coordinator,
+                packageFQName,
+                packageInterfaces,
+                typesAST,
+                true /* forJava */);
+
+        out << "\ninclude $(BUILD_JAVA_LIBRARY)\n";
+    }
+
     return OK;
 }
 
-OutputHandler::ValRes validateForMakefile(const FQName &fqName) {
+OutputHandler::ValRes validateForMakefile(
+        const FQName &fqName, const std::string & /* language */) {
     if (fqName.package().empty()) {
         fprintf(stderr, "ERROR: Expecting package name\n");
         return OutputHandler::FAILED;
@@ -255,7 +373,8 @@
     return OutputHandler::PASS_PACKAGE;
 }
 
-OutputHandler::ValRes validateForSource(const FQName &fqName) {
+OutputHandler::ValRes validateForSource(
+        const FQName &fqName, const std::string &language) {
     if (fqName.package().empty()) {
         fprintf(stderr, "ERROR: Expecting package name\n");
         return OutputHandler::FAILED;
@@ -266,9 +385,26 @@
         return OutputHandler::FAILED;
     }
 
-    return fqName.name().empty() ?
-        OutputHandler::PASS_PACKAGE :
-        OutputHandler::PASS_FULL;
+    const std::string &name = fqName.name();
+    if (!name.empty()) {
+        if (name.find('.') == std::string::npos) {
+            return OutputHandler::PASS_FULL;
+        }
+
+        if (language != "java" || name.find("types.") != 0) {
+            // When generating java sources for "types.hal", output can be
+            // constrained to just one of the top-level types declared
+            // by using the extended syntax
+            // android.hardware.Foo@1.0::types.TopLevelTypeName.
+            // In all other cases (different language, not 'types') the dot
+            // notation in the name is illegal in this context.
+            return OutputHandler::FAILED;
+        }
+
+        return OutputHandler::PASS_FULL;
+    }
+
+    return OutputHandler::PASS_PACKAGE;
 }
 
 static std::vector<OutputHandler> formats = {
@@ -282,12 +418,14 @@
                         return generateSourcesForFile(fqName,
                                                       hidl_gen,
                                                       coordinator,
-                                                      outputDir, "c++");
+                                                      outputDir,
+                                                      "c++");
             } else {
                         return generateSourcesForPackage(fqName,
                                                          hidl_gen,
                                                          coordinator,
-                                                         outputDir, "c++");
+                                                         outputDir,
+                                                         "c++");
             }
         }
     },
@@ -302,13 +440,15 @@
                 return generateSourcesForFile(fqName,
                                               hidl_gen,
                                               coordinator,
-                                              outputDir, "java");
+                                              outputDir,
+                                              "java");
             }
             else {
                 return generateSourcesForPackage(fqName,
                                                  hidl_gen,
                                                  coordinator,
-                                                 outputDir, "java");
+                                                 outputDir,
+                                                 "java");
             }
         }
     },
@@ -460,7 +600,9 @@
             exit(1);
         }
 
-        OutputHandler::ValRes valid = outputFormat->validate(fqName);
+        OutputHandler::ValRes valid =
+            outputFormat->validate(fqName, outputFormat->mKey);
+
         if (valid == OutputHandler::FAILED) {
             exit(1);
         }
diff --git a/test/data/android/hardware/nfc/1.0/Nfc.vts b/test/data/android/hardware/nfc/1.0/Nfc.vts
index 6d70ff6..4dd78f6 100644
--- a/test/data/android/hardware/nfc/1.0/Nfc.vts
+++ b/test/data/android/hardware/nfc/1.0/Nfc.vts
@@ -1,5 +1,4 @@
 component_class: HAL_HIDL
-component_type: NFC
 component_type_version: 1.0
 component_name: "INfc"
 
@@ -13,11 +12,12 @@
     name: "open"
     return_type_hidl: {
       type: TYPE_SCALAR
-      scalar_type: int32_t
+      scalar_type: "int32_t"
     }
     arg: {
       type: TYPE_HIDL_CALLBACK
       predefined_type: "INfcClientCallback"
+      is_callback: true
     }
   }
 
@@ -25,7 +25,7 @@
     name: "write"
     return_type_hidl: {
       type: TYPE_SCALAR
-      scalar_type: int32_t
+      scalar_type: "int32_t"
     }
     arg: {
       type: TYPE_STRUCT
@@ -37,13 +37,13 @@
     name: "core_initialized"
     return_type_hidl: {
       type: TYPE_SCALAR
-      scalar_type: int32_t
+      scalar_type: "int32_t"
     }
     arg: {
       type: TYPE_VECTOR
       vector_value: {
         type: TYPE_SCALAR
-        scalar_type: uint8_t
+        scalar_type: "uint8_t"
       }
     }
   }
@@ -52,7 +52,7 @@
     name: "pre_discover"
     return_type_hidl: {
       type: TYPE_SCALAR
-      scalar_type: int32_t
+      scalar_type: "int32_t"
     }
   }
 
@@ -60,7 +60,7 @@
     name: "close"
     return_type_hidl: {
       type: TYPE_SCALAR
-      scalar_type: int32_t
+      scalar_type: "int32_t"
     }
   }
 
@@ -68,7 +68,7 @@
     name: "control_granted"
     return_type_hidl: {
       type: TYPE_SCALAR
-      scalar_type: int32_t
+      scalar_type: "int32_t"
     }
   }
 
@@ -76,7 +76,7 @@
     name: "power_cycle"
     return_type_hidl: {
       type: TYPE_SCALAR
-      scalar_type: int32_t
+      scalar_type: "int32_t"
     }
   }
 
diff --git a/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts b/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
index fb34126..39d1ef8 100644
--- a/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
+++ b/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
@@ -1,5 +1,4 @@
 component_class: HAL_HIDL
-component_type: NFC
 component_type_version: 1.0
 component_name: "INfcClientCallback"
 
@@ -12,11 +11,11 @@
     name: "sendEvent"
     arg: {
       type: TYPE_ENUM
-      predefined_type:"nfc_event_t"
+      predefined_type: "nfc_event_t"
     }
     arg: {
       type: TYPE_ENUM
-      predefined_type:"nfc_status_t"
+      predefined_type: "nfc_status_t"
     }
   }
 
diff --git a/test/data/android/hardware/nfc/1.0/types.vts b/test/data/android/hardware/nfc/1.0/types.vts
index 89a3fba..b8cbb59 100644
--- a/test/data/android/hardware/nfc/1.0/types.vts
+++ b/test/data/android/hardware/nfc/1.0/types.vts
@@ -51,7 +51,7 @@
     type: TYPE_VECTOR
     vector_value: {
       type: TYPE_SCALAR
-      scalar_type: uint8_t
+      scalar_type: "uint8_t"
     }
   }
 }
diff --git a/test/data/android/hardware/tests/expression/1.0/BnExpression.h b/test/data/android/hardware/tests/expression/1.0/BnExpression.h
new file mode 100644
index 0000000..99a8137
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/BnExpression.h
@@ -0,0 +1,32 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_BnExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_BnExpression_H_
+
+#include <android/hardware/tests/expression/1.0/IHwExpression.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct BnExpression : public ::android::hardware::BnInterface<IExpression, IHwExpression> {
+  explicit BnExpression(const ::android::sp<IExpression> &_hidl_impl);
+
+  ::android::status_t onTransact(
+      uint32_t _hidl_code,
+      const ::android::hardware::Parcel &_hidl_data,
+      ::android::hardware::Parcel *_hidl_reply,
+      uint32_t _hidl_flags = 0,
+      TransactCallback _hidl_cb = nullptr) override;
+
+  // Methods from IExpression follow.
+
+};
+
+}  // namespace V1_0
+}  // namespace expression
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_tests_expression_V1_0_BnExpression_H_
diff --git a/test/data/android/hardware/tests/expression/1.0/BpExpression.h b/test/data/android/hardware/tests/expression/1.0/BpExpression.h
new file mode 100644
index 0000000..bb4edae
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/BpExpression.h
@@ -0,0 +1,27 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_BpExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_BpExpression_H_
+
+#include <android/hardware/tests/expression/1.0/IHwExpression.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct BpExpression : public ::android::hardware::BpInterface<IHwExpression> {
+  explicit BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);
+
+  virtual bool isRemote() const { return true; } 
+
+  // Methods from IExpression follow.
+
+};
+
+}  // namespace V1_0
+}  // namespace expression
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_tests_expression_V1_0_BpExpression_H_
diff --git a/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp b/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
new file mode 100644
index 0000000..6664fa1
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
@@ -0,0 +1,50 @@
+#include <android/hardware/tests/expression/1.0//BpExpression.h>
+#include <android/hardware/tests/expression/1.0//BnExpression.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+BpExpression::BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)
+    : BpInterface<IHwExpression>(_hidl_impl) {
+}
+
+IMPLEMENT_HWBINDER_META_INTERFACE(Expression, "android.hardware.tests.expression@1.0::IExpression");
+
+BnExpression::BnExpression(const ::android::sp<IExpression> &_hidl_impl)
+    : BnInterface<IExpression, IHwExpression>(_hidl_impl) {
+}
+
+::android::status_t BnExpression::onTransact(
+    uint32_t _hidl_code,
+    const ::android::hardware::Parcel &_hidl_data,
+    ::android::hardware::Parcel *_hidl_reply,
+    uint32_t _hidl_flags,
+    TransactCallback _hidl_cb) {
+  ::android::status_t _hidl_err = ::android::OK;
+
+  switch (_hidl_code) {
+    default:
+    {
+      return ::android::hardware::BnInterface<IExpression, IHwExpression>::onTransact(
+          _hidl_code, _hidl_data, _hidl_reply, _hidl_flags, _hidl_cb);
+    }
+  }
+
+  if (_hidl_err == ::android::UNEXPECTED_NULL) {
+    _hidl_err = ::android::hardware::Status::fromExceptionCode(
+        ::android::hardware::Status::EX_NULL_POINTER)
+            .writeToParcel(_hidl_reply);
+  }
+
+  return _hidl_err;
+}
+
+IMPLEMENT_REGISTER_AND_GET_SERVICE(Expression)
+}  // namespace V1_0
+}  // namespace expression
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
diff --git a/test/data/android/hardware/tests/expression/1.0/IExpression.h b/test/data/android/hardware/tests/expression/1.0/IExpression.h
new file mode 100644
index 0000000..a8def3b
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/IExpression.h
@@ -0,0 +1,142 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_IExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_IExpression_H_
+
+#include <hidl/HidlSupport.h>
+#include <hidl/IServiceManager.h>
+#include <hwbinder/Status.h>
+#include <utils/NativeHandle.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct IExpression : virtual public RefBase {
+  enum class UInt64LiteralTypeGuessing : uint64_t {
+    noSuffixDec1 = 0ull, // (int32_t)0
+    noSuffixDec2 = 1ull, // (int32_t)1
+    noSuffixDec3 = 18446744073709551615ull, // (int32_t)(-1)
+    noSuffixDec4 = 18446744073709551615ull, // (int32_t)(~0)
+    noSuffixDec5 = 2147483647ull, // (int32_t)2147483647
+    noSuffixDec6 = 18446744071562067968ull, // (int64_t)(-2147483648)
+    noSuffixDec7 = 2147483648ull, // (int64_t)2147483648
+    noSuffixDec8 = 18446744071562067967ull, // (int64_t)(-2147483649)
+    noSuffixDec9 = 0ull, // (int32_t)(~(-1))
+    noSuffixHex1 = 2147483647ull, // (int32_t)0x7fffffff
+    noSuffixHex2 = 2147483648ull, // (uint32_t)0x80000000
+    noSuffixHex3 = 4294967295ull, // (uint32_t)0xffffffff
+    longHex1 = 4294967295ull, // (int64_t)0xffffffffl
+    longHex2 = 68719476735ull, // (int64_t)0xfffffffff
+    longHex3 = 9223372036854775807ull, // (int64_t)0x7fffffffffffffff
+    longHex4 = 9223372036854775808ull, // (uint64_t)0x8000000000000000
+    longHex5 = 18446744073709551615ull, // (uint64_t)0xFFFFFFFFFFFFFFFF
+  };
+
+  enum class SuffixedLiteralTypeGuessing : int32_t {
+    decInt32_1 = 1, // (bool)((~(-1)) == 0)
+    decInt32_2 = 1, // (bool)((-(1 << 31)) == (1 << 31))
+    decInt64_1 = 1, // (bool)((~(-1l)) == 0)
+    decInt64_2 = 1, // (bool)((~4294967295) != 0)
+    decInt64_3 = 1, // (bool)((~4294967295l) != 0)
+    decInt64_4 = 1, // (bool)((-(1l << 63)) == (1l << 63))
+    hexInt32_1 = 1, // (bool)((-0x7fffffff) < 0)
+    hexUInt32_1 = 1, // (bool)((-0x80000000) > 0)
+    hexUInt32_2 = 1, // (bool)((~0xFFFFFFFF) == 0)
+    hexInt64_1 = 1, // (bool)((-0x7FFFFFFFFFFFFFFF) < 0)
+    hexUInt64_1 = 1, // (bool)((-0x8000000000000000) > 0)
+  };
+
+  enum class Int64LiteralTypeGuessing : int64_t {
+    noSuffixDec11 = -2147483648ll, // (int32_t)(1 + 0x7fffffff)
+    noSuffixDec12 = 2147483647ll, // (uint32_t)(0x80000000 - 1)
+  };
+
+  enum class Int32BitShifting : int32_t {
+    int32BitShift1 = -2147483648, // (int32_t)(1 << 31)
+  };
+
+  enum class UInt32BitShifting : uint32_t {
+    uint32BitShift1 = 2147483648u, // (int32_t)(1 << 31)
+  };
+
+  enum class Int64BitShifting : int64_t {
+    int64BitShift1 = (int64_t)(-9223372036854775808ull), // (int64_t)(1l << 63)
+  };
+
+  enum class UInt64BitShifting : uint64_t {
+    uint64BitShift1 = 9223372036854775808ull, // (int64_t)(1l << 63)
+  };
+
+  enum class Precedence : int32_t {
+    literal = 4, // (int32_t)4
+    neg = -4, // (int32_t)(-4)
+    literalL = -4, // (int64_t)(-4L)
+    hex = -1, // (uint32_t)0xffffffff
+    hexLong = -1, // (int64_t)0xffffffffl
+    hexLong2 = -1, // (int64_t)0xfffffffff
+    simpleArithmetic = 5, // (int32_t)(4 + 1)
+    simpleArithmetic2 = 1, // (int32_t)((2 + 3) - 4)
+    simpleBoolExpr = 0, // (bool)(1 == 4)
+    simpleLogical = 1, // (bool)(1 && 1)
+    simpleComp = 1, // (bool)(1 < 2)
+    boolExpr1 = 0, // (bool)(!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0))
+    boolExpr = 0, // (bool)((1 == 7) && (!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0)))
+    simpleBitShift = 4, // (int32_t)(1 << 2)
+    simpleBitShift2 = 2, // (int32_t)(4 >> 1)
+    simpleBitShiftNeg = 2, // (int32_t)(4 << (-1))
+    simpleArithmeticRightShift = -1, // (int32_t)((1 << 31) >> 31)
+    simpleBitExpr = 5, // (int32_t)(1 | (16 >> 2))
+    bitExpr = 3, // (int32_t)(((~42) & ((1 << 3) | (16 >> 2))) ^ 7)
+    arithmeticExpr = 33, // (int32_t)((2 + 3) - ((4 * (-7)) / (10 % 3)))
+    messyExpr = 2, // (int32_t)(2 + ((-3) & (4 / 7)))
+    paranExpr = 2, // (int32_t)(1 + 1)
+    ternary = 2, // (int32_t)(1?2:3)
+    ternary2 = 3, // (int32_t)((1 && 2)?3:4)
+    complicatedTernary2 = 56, // (int32_t)((((1 - 1) && (2 + 3)) || 5)?(7 * 8):(-3))
+  };
+
+  enum class OperatorSanityCheck : int32_t {
+    plus = 1, // (bool)((1 + 2) == 3)
+    minus = 1, // (bool)((8 - 9) == (-1))
+    product = 1, // (bool)((9 * 9) == 81)
+    division = 1, // (bool)((29 / 3) == 9)
+    mod = 1, // (bool)((29 % 3) == 2)
+    bit_or = 1, // (bool)((0xC0010000 | 0xF00D) == 0xC001F00D)
+    bit_or2 = 1, // (bool)((10 | 6) == 14)
+    bit_and = 1, // (bool)((10 & 6) == 2)
+    bit_xor = 1, // (bool)((10 ^ 6) == 12)
+    lt1 = 1, // (bool)(6 < 10)
+    lt2 = 1, // (bool)((10 < 10) == 0)
+    gt1 = 1, // (bool)((6 > 10) == 0)
+    gt2 = 1, // (bool)((10 > 10) == 0)
+    gte1 = 1, // (bool)(19 >= 10)
+    gte2 = 1, // (bool)(10 >= 10)
+    lte1 = 1, // (bool)(5 <= 10)
+    lte2 = 1, // (bool)((19 <= 10) == 0)
+    ne1 = 1, // (bool)(19 != 10)
+    ne2 = 1, // (bool)((10 != 10) == 0)
+    lshift = 1, // (bool)((22 << 1) == 44)
+    rshift = 1, // (bool)((11 >> 1) == 5)
+    logor1 = 1, // (bool)((1 || 0) == 1)
+    logor2 = 1, // (bool)((1 || 1) == 1)
+    logor3 = 1, // (bool)((0 || 0) == 0)
+    logor4 = 1, // (bool)((0 || 1) == 1)
+    logand1 = 1, // (bool)((1 && 0) == 0)
+    logand2 = 1, // (bool)((1 && 1) == 1)
+    logand3 = 1, // (bool)((0 && 0) == 0)
+    logand4 = 1, // (bool)((0 && 1) == 0)
+  };
+
+  virtual bool isRemote() const { return false; } 
+
+  DECLARE_REGISTER_AND_GET_SERVICE(Expression)
+};
+
+}  // namespace V1_0
+}  // namespace expression
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_tests_expression_V1_0_IExpression_H_
diff --git a/test/data/android/hardware/tests/expression/1.0/IExpression.java b/test/data/android/hardware/tests/expression/1.0/IExpression.java
new file mode 100644
index 0000000..ebc0bf9
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/IExpression.java
@@ -0,0 +1,180 @@
+package android.hardware.tests.expression.V1_0;
+
+import android.os.IHwBinder;
+import android.os.IHwInterface;
+import android.os.HwBinder;
+import android.os.HwBlob;
+import android.os.HwParcel;
+
+import java.util.Vector;
+
+public interface IExpression extends IHwInterface {
+  public static final String kInterfaceName = "android.hardware.tests.expression@1.0::IExpression";
+
+  public static IExpression asInterface(IHwBinder binder) {
+    if (binder == null) {
+      return null;
+    }
+
+    IHwInterface iface =
+        binder.queryLocalInterface(kInterfaceName);
+
+    if ((iface != null) && (iface instanceof IExpression)) {
+      return (IExpression)iface;
+    }
+
+    return new IExpression.Proxy(binder);
+  }
+
+  public IHwBinder asBinder();
+
+  public final class UInt64LiteralTypeGuessing {
+    public static final long noSuffixDec1 = 0L; // (int32_t)0
+    public static final long noSuffixDec2 = 1L; // (int32_t)1
+    public static final long noSuffixDec3 = -1L; // (int32_t)(-1)
+    public static final long noSuffixDec4 = -1L; // (int32_t)(~0)
+    public static final long noSuffixDec5 = 2147483647L; // (int32_t)2147483647
+    public static final long noSuffixDec6 = -2147483648L; // (int64_t)(-2147483648)
+    public static final long noSuffixDec7 = 2147483648L; // (int64_t)2147483648
+    public static final long noSuffixDec8 = -2147483649L; // (int64_t)(-2147483649)
+    public static final long noSuffixDec9 = 0L; // (int32_t)(~(-1))
+    public static final long noSuffixHex1 = 2147483647L; // (int32_t)0x7fffffff
+    public static final long noSuffixHex2 = 2147483648L; // (uint32_t)0x80000000
+    public static final long noSuffixHex3 = 4294967295L; // (uint32_t)0xffffffff
+    public static final long longHex1 = 4294967295L; // (int64_t)0xffffffffl
+    public static final long longHex2 = 68719476735L; // (int64_t)0xfffffffff
+    public static final long longHex3 = 9223372036854775807L; // (int64_t)0x7fffffffffffffff
+    public static final long longHex4 = -9223372036854775808L; // (uint64_t)0x8000000000000000
+    public static final long longHex5 = -1L; // (uint64_t)0xFFFFFFFFFFFFFFFF
+  };
+
+  public final class SuffixedLiteralTypeGuessing {
+    public static final int decInt32_1 = 1; // (bool)((~(-1)) == 0)
+    public static final int decInt32_2 = 1; // (bool)((-(1 << 31)) == (1 << 31))
+    public static final int decInt64_1 = 1; // (bool)((~(-1l)) == 0)
+    public static final int decInt64_2 = 1; // (bool)((~4294967295) != 0)
+    public static final int decInt64_3 = 1; // (bool)((~4294967295l) != 0)
+    public static final int decInt64_4 = 1; // (bool)((-(1l << 63)) == (1l << 63))
+    public static final int hexInt32_1 = 1; // (bool)((-0x7fffffff) < 0)
+    public static final int hexUInt32_1 = 1; // (bool)((-0x80000000) > 0)
+    public static final int hexUInt32_2 = 1; // (bool)((~0xFFFFFFFF) == 0)
+    public static final int hexInt64_1 = 1; // (bool)((-0x7FFFFFFFFFFFFFFF) < 0)
+    public static final int hexUInt64_1 = 1; // (bool)((-0x8000000000000000) > 0)
+  };
+
+  public final class Int64LiteralTypeGuessing {
+    public static final long noSuffixDec11 = -2147483648L; // (int32_t)(1 + 0x7fffffff)
+    public static final long noSuffixDec12 = 2147483647L; // (uint32_t)(0x80000000 - 1)
+  };
+
+  public final class Int32BitShifting {
+    public static final int int32BitShift1 = -2147483648; // (int32_t)(1 << 31)
+  };
+
+  public final class UInt32BitShifting {
+    public static final int uint32BitShift1 = -2147483648; // (int32_t)(1 << 31)
+  };
+
+  public final class Int64BitShifting {
+    public static final long int64BitShift1 = -9223372036854775808L; // (int64_t)(1l << 63)
+  };
+
+  public final class UInt64BitShifting {
+    public static final long uint64BitShift1 = -9223372036854775808L; // (int64_t)(1l << 63)
+  };
+
+  public final class Precedence {
+    public static final int literal = 4; // (int32_t)4
+    public static final int neg = -4; // (int32_t)(-4)
+    public static final int literalL = -4; // (int64_t)(-4L)
+    public static final int hex = -1; // (uint32_t)0xffffffff
+    public static final int hexLong = -1; // (int64_t)0xffffffffl
+    public static final int hexLong2 = -1; // (int64_t)0xfffffffff
+    public static final int simpleArithmetic = 5; // (int32_t)(4 + 1)
+    public static final int simpleArithmetic2 = 1; // (int32_t)((2 + 3) - 4)
+    public static final int simpleBoolExpr = 0; // (bool)(1 == 4)
+    public static final int simpleLogical = 1; // (bool)(1 && 1)
+    public static final int simpleComp = 1; // (bool)(1 < 2)
+    public static final int boolExpr1 = 0; // (bool)(!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0))
+    public static final int boolExpr = 0; // (bool)((1 == 7) && (!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0)))
+    public static final int simpleBitShift = 4; // (int32_t)(1 << 2)
+    public static final int simpleBitShift2 = 2; // (int32_t)(4 >> 1)
+    public static final int simpleBitShiftNeg = 2; // (int32_t)(4 << (-1))
+    public static final int simpleArithmeticRightShift = -1; // (int32_t)((1 << 31) >> 31)
+    public static final int simpleBitExpr = 5; // (int32_t)(1 | (16 >> 2))
+    public static final int bitExpr = 3; // (int32_t)(((~42) & ((1 << 3) | (16 >> 2))) ^ 7)
+    public static final int arithmeticExpr = 33; // (int32_t)((2 + 3) - ((4 * (-7)) / (10 % 3)))
+    public static final int messyExpr = 2; // (int32_t)(2 + ((-3) & (4 / 7)))
+    public static final int paranExpr = 2; // (int32_t)(1 + 1)
+    public static final int ternary = 2; // (int32_t)(1?2:3)
+    public static final int ternary2 = 3; // (int32_t)((1 && 2)?3:4)
+    public static final int complicatedTernary2 = 56; // (int32_t)((((1 - 1) && (2 + 3)) || 5)?(7 * 8):(-3))
+  };
+
+  public final class OperatorSanityCheck {
+    public static final int plus = 1; // (bool)((1 + 2) == 3)
+    public static final int minus = 1; // (bool)((8 - 9) == (-1))
+    public static final int product = 1; // (bool)((9 * 9) == 81)
+    public static final int division = 1; // (bool)((29 / 3) == 9)
+    public static final int mod = 1; // (bool)((29 % 3) == 2)
+    public static final int bit_or = 1; // (bool)((0xC0010000 | 0xF00D) == 0xC001F00D)
+    public static final int bit_or2 = 1; // (bool)((10 | 6) == 14)
+    public static final int bit_and = 1; // (bool)((10 & 6) == 2)
+    public static final int bit_xor = 1; // (bool)((10 ^ 6) == 12)
+    public static final int lt1 = 1; // (bool)(6 < 10)
+    public static final int lt2 = 1; // (bool)((10 < 10) == 0)
+    public static final int gt1 = 1; // (bool)((6 > 10) == 0)
+    public static final int gt2 = 1; // (bool)((10 > 10) == 0)
+    public static final int gte1 = 1; // (bool)(19 >= 10)
+    public static final int gte2 = 1; // (bool)(10 >= 10)
+    public static final int lte1 = 1; // (bool)(5 <= 10)
+    public static final int lte2 = 1; // (bool)((19 <= 10) == 0)
+    public static final int ne1 = 1; // (bool)(19 != 10)
+    public static final int ne2 = 1; // (bool)((10 != 10) == 0)
+    public static final int lshift = 1; // (bool)((22 << 1) == 44)
+    public static final int rshift = 1; // (bool)((11 >> 1) == 5)
+    public static final int logor1 = 1; // (bool)((1 || 0) == 1)
+    public static final int logor2 = 1; // (bool)((1 || 1) == 1)
+    public static final int logor3 = 1; // (bool)((0 || 0) == 0)
+    public static final int logor4 = 1; // (bool)((0 || 1) == 1)
+    public static final int logand1 = 1; // (bool)((1 && 0) == 0)
+    public static final int logand2 = 1; // (bool)((1 && 1) == 1)
+    public static final int logand3 = 1; // (bool)((0 && 0) == 0)
+    public static final int logand4 = 1; // (bool)((0 && 1) == 0)
+  };
+
+  public static final int kOpEnd = IHwBinder.FIRST_CALL_TRANSACTION + 0;
+
+
+  public static final class Proxy implements IExpression {
+    private IHwBinder mRemote;
+
+    public Proxy(IHwBinder remote) {
+      mRemote = remote;
+    }
+
+    public IHwBinder asBinder() {
+      return mRemote;
+    }
+
+    // Methods from ::android::hardware::tests::expression::V1_0::IExpression follow.
+  }
+
+  public static abstract class Stub extends HwBinder implements IExpression {
+    public IHwBinder asBinder() {
+      return this;
+    }
+
+    public IHwInterface queryLocalInterface(String descriptor) {
+      if (kInterfaceName.equals(descriptor)) {
+        return this;
+      }
+      return null;
+    }
+
+    public void onTransact(int code, HwParcel request, final HwParcel reply, int flags) {
+      switch (code) {
+      }
+    }
+  }
+}
diff --git a/test/data/android/hardware/tests/expression/1.0/IHwExpression.h b/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
new file mode 100644
index 0000000..d9ad8aa
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
@@ -0,0 +1,33 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_IHwExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_IHwExpression_H_
+
+#include <android/hardware/tests/expression/1.0/IExpression.h>
+
+
+#include <hidl/HidlSupport.h>
+#include <hwbinder/IBinder.h>
+#include <hwbinder/IInterface.h>
+#include <hwbinder/Status.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct IHwExpression : public IExpression, public ::android::hardware::IInterface {
+  DECLARE_HWBINDER_META_INTERFACE(Expression);
+
+  enum Call {
+    CallCount
+  };
+
+};
+
+}  // namespace V1_0
+}  // namespace expression
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_tests_expression_V1_0_IHwExpression_H_
diff --git a/test/java_test/Android.mk b/test/java_test/Android.mk
index 84474cc..97a95ec 100644
--- a/test/java_test/Android.mk
+++ b/test/java_test/Android.mk
@@ -5,23 +5,9 @@
 LOCAL_MODULE := hidl_test_java_lib
 LOCAL_MODULE_STEM := hidl_test_java
 LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(local-generated-sources-dir)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-GEN := $(intermediates)/android/hardware/tests/baz/1.0/IBaz.java              \
-       $(intermediates)/android/hardware/tests/baz/1.0/IBazCallback.java      \
-       $(intermediates)/android/hardware/tests/baz/1.0/IBase.java             \
-
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = $(PRIVATE_HIDL) -Ljava -randroid.hardware:hardware/interfaces -o $(PRIVATE_OUTPUT_DIR) android.hardware.tests.baz@1.0
-$(GEN):
-	$(transform-generated-source)
-
-LOCAL_GENERATED_SOURCES += $(GEN)
+LOCAL_JAVA_LIBRARIES := 			   \
+	android.hardware.tests.baz@1.0-java	   \
+	android.hardware.tests.expression@1.0-java
 
 include $(BUILD_JAVA_LIBRARY)
 
@@ -31,7 +17,11 @@
 LOCAL_MODULE := hidl_test_java
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_SRC_FILES := hidl_test_java
-LOCAL_REQUIRED_MODULES := hidl_test_java_lib
+
+LOCAL_REQUIRED_MODULES :=                       \
+    hidl_test_java_lib                          \
+    android.hardware.tests.baz@1.0-java
+
 include $(BUILD_PREBUILT)
 
 ################################################################################
@@ -48,6 +38,7 @@
     libhwbinder                     \
     libutils                        \
     android.hardware.tests.baz@1.0  \
+    android.hardware.tests.expression@1.0
 
 LOCAL_STATIC_LIBRARIES := \
     libgtest
diff --git a/test/java_test/hidl_test_java b/test/java_test/hidl_test_java
index 71a16c2..e1171cc 100644
--- a/test/java_test/hidl_test_java
+++ b/test/java_test/hidl_test_java
@@ -1,5 +1,5 @@
 base=/system
-export CLASSPATH=$base/framework/hidl_test_java.jar
+export CLASSPATH=$base/framework/hidl_test_java.jar:$base/framework/android.hardware.tests.baz@1.0-java.jar
 
 # Test native server with Java client
 hidl_test_java_native -s &
diff --git a/test/java_test/hidl_test_java_native.cpp b/test/java_test/hidl_test_java_native.cpp
index d831435..6ec7263 100644
--- a/test/java_test/hidl_test_java_native.cpp
+++ b/test/java_test/hidl_test_java_native.cpp
@@ -3,9 +3,7 @@
 
 #include <android-base/logging.h>
 
-#include <android/hardware/tests/baz/1.0/BnBaz.h>
-#include <android/hardware/tests/baz/1.0/BnBazCallback.h>
-#include <android/hardware/tests/baz/1.0/BpBaz.h>
+#include <android/hardware/tests/baz/1.0/IBaz.h>
 
 #include <gtest/gtest.h>
 #include <hidl/IServiceManager.h>
@@ -18,16 +16,13 @@
 using ::android::hardware::tests::baz::V1_0::IBase;
 using ::android::hardware::tests::baz::V1_0::IBaz;
 using ::android::hardware::tests::baz::V1_0::IBazCallback;
-using ::android::hardware::tests::baz::V1_0::BnBaz;
-using ::android::hardware::tests::baz::V1_0::BnBazCallback;
-using ::android::hardware::tests::baz::V1_0::BpBaz;
 
 using ::android::hardware::hidl_vec;
 using ::android::hardware::hidl_string;
 using ::android::hardware::Return;
 using ::android::hardware::Status;
 
-struct BazCallback : public BnBazCallback {
+struct BazCallback : public IBazCallback {
     Status heyItsMe(const sp<IBazCallback> &cb) override;
 };
 
@@ -38,7 +33,7 @@
     return Status::ok();
 }
 
-struct Baz : public BnBaz {
+struct Baz : public IBaz {
     Status someBaseMethod() override;
 
     Status someOtherBaseMethod(
@@ -349,13 +344,8 @@
 
         const hidl_version kVersion = make_hidl_version(1, 0);
 
-        sp<IBinder> service =
-            defaultServiceManager()->getService(
-                    ::android::String16("baz"), kVersion);
+        baz = IBaz::getService(::android::String16("baz"), kVersion);
 
-        CHECK(service != NULL);
-
-        baz = IBaz::asInterface(service);
         CHECK(baz != NULL);
     }
 
@@ -599,7 +589,7 @@
 
         const hidl_version kVersion = make_hidl_version(1, 0);
 
-        defaultServiceManager()->addService(String16("baz"), baz, kVersion);
+        baz->registerAsService(String16("baz"), kVersion);
 
         ProcessState::self()->startThreadPool();
         ProcessState::self()->setThreadPoolMaxThreadCount(0);
diff --git a/test/main.cpp b/test/main.cpp
index 72ec8cd..ae973db 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -30,6 +30,7 @@
 using ::android::hardware::tests::foo::V1_0::IFoo;
 using ::android::hardware::tests::foo::V1_0::IFooCallback;
 using ::android::hardware::tests::bar::V1_0::IBar;
+using ::android::hardware::tests::bar::V1_0::IHwBar;
 using ::android::hardware::tests::foo::V1_0::Abc;
 using ::android::hardware::Return;
 using ::android::hardware::Status;
@@ -39,7 +40,7 @@
 using ::android::Mutex;
 using ::android::Condition;
 
-struct FooCallback : public BnFooCallback {
+struct FooCallback : public IFooCallback {
     FooCallback() : invokeInfo{}, mLock{}, mCond{} {}
     Status heyItsYou(const sp<IFooCallback> &cb) override;
     Return<bool> heyItsYouIsntIt(const sp<IFooCallback> &cb) override;
@@ -96,7 +97,7 @@
 }
 
 Status FooCallback::reportResults(int64_t ns, reportResults_cb cb) {
-    ALOGI("SERVER(FooCallback) reportResults(%" PRId64 ") seconds", nanoseconds_to_seconds(ns));
+    ALOGI("SERVER(FooCallback) reportResults(%" PRId64 " seconds)", nanoseconds_to_seconds(ns));
     nsecs_t leftToWaitNs = ns;
     mLock.lock();
     while (!(invokeInfo[0].invoked && invokeInfo[1].invoked && invokeInfo[2].invoked) &&
@@ -104,10 +105,10 @@
       nsecs_t start = systemTime();
       ::android::status_t rc = mCond.waitRelative(mLock, leftToWaitNs);
       if (rc != ::android::OK) {
-          ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 ") Condition::waitRelative(%" PRId64 ") returned error (%d)", ns, leftToWaitNs, rc);
+          ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 " ns) Condition::waitRelative(%" PRId64 ") returned error (%d)", ns, leftToWaitNs, rc);
           break;
       }
-      ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 ") Condition::waitRelative was signalled", ns);
+      ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 " ns) Condition::waitRelative was signalled", ns);
       leftToWaitNs -= systemTime() - start;
     }
     mLock.unlock();
@@ -122,7 +123,7 @@
     return Status::ok();
 }
 
-struct Bar : public BnBar {
+struct Bar : public IBar {
     Status doThis(float param) override;
 
     Return<int32_t> doThatAndReturnSomething(int64_t param) override;
@@ -388,7 +389,7 @@
     using namespace android::hardware;
     using android::String16;
     ALOGI("SERVER(%s) registering", tag);
-    defaultServiceManager()->addService(String16(serviceName), server, kVersion);
+    server->registerAsService(String16(serviceName), kVersion);
     ALOGI("SERVER(%s) starting", tag);
     ProcessState::self()->setThreadPoolMaxThreadCount(0);
     ProcessState::self()->startThreadPool();
@@ -410,22 +411,13 @@
         using android::String16;
         const hidl_version kVersion = make_hidl_version(1, 0);
 
-        service =
-            defaultServiceManager()->getService(String16("foo"), kVersion);
-        ALOGI("CLIENT Found service foo.");
-
-        CHECK(service != NULL);
-
-        foo = IFoo::asInterface(service);
+        foo = IFoo::getService(String16("foo"), kVersion);
         CHECK(foo != NULL);
 
-        bar = IBar::asInterface(service);
+        bar = IBar::getService(String16("foo"), kVersion);
         CHECK(bar != NULL);
 
-        cbService = defaultServiceManager()->getService(String16("foo callback"), kVersion);
-        CHECK(cbService != NULL);
-
-        fooCb = IFooCallback::asInterface(cbService);
+        fooCb = IFooCallback::getService(String16("foo callback"), kVersion);
         CHECK(fooCb != NULL);
 
         ALOGI("Test setup complete");
@@ -574,8 +566,8 @@
     // time to execute that we also expect.
 
     const nsecs_t reportResultsNs =
-          seconds_to_nanoseconds(2*(FooCallback::DELAY_S +
-                                    FooCallback::TOLERANCE_NS));
+        2 * FooCallback::DELAY_NS + FooCallback::TOLERANCE_NS;
+
     ALOGI("CLIENT: Waiting for up to %" PRId64 " seconds.",
           nanoseconds_to_seconds(reportResultsNs));
 
diff --git a/test/test_output.py b/test/test_output.py
index 09c806b..b435cf0 100644
--- a/test/test_output.py
+++ b/test/test_output.py
@@ -60,8 +60,8 @@
     def testAll(self):
         """Run all tests. """
         self.TestVtsOutput()
-        # Uncomment once we want to test cpp output.
-        # self.TestCppOutput()
+        self.TestCppOutput()
+        self.TestJavaOutput()
 
     def TestVtsOutput(self):
         """Runs hidl-gen to generate vts file and verify the output."""
@@ -71,8 +71,15 @@
 
     def TestCppOutput(self):
         """Runs hidl-gen to generate c++ file and verify the output."""
-        self.RunTest("c++", "android.hardware.nfc@1.0",
-                     "android/hardware/nfc/1.0")
+        # self.RunTest("c++", "android.hardware.nfc@1.0",
+        #              "android/hardware/nfc/1.0")
+        self.RunTest("c++", "android.hardware.tests.expression@1.0",
+                     "android/hardware/tests/expression/1.0")
+        self.assertEqual(self._errors, 0)
+
+    def TestJavaOutput(self):
+        self.RunTest("java", "android.hardware.tests.expression@1.0",
+                     "android/hardware/tests/expression/1.0")
         self.assertEqual(self._errors, 0)
 
     def RunTest(self, language, fqname, package_path):