Add @Enforce AIDL annotation

If used, this annotation will add logic in the Binder stub to verify the
caller's permissions. The annotation is in the format:

@Enforce(condition="permission = READ_PHONE_STATE || uid = SYSTEM_UID")
void Method();

Permissions should be constants defined in the
android.Manifest.permission class. UIDs should be constants defined in
the android.os.Process class.

Only Java service implementations are supported for now.

Bug: 197828948
Test: aidl-golden-test
Change-Id: Id80680de4ba09fcfacbb66079fa4d015809001b7
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index 7a738cd..12aee22 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -16,10 +16,12 @@
 
 #include "aidl.h"
 #include "aidl_to_java.h"
+#include "aidl_typenames.h"
 #include "ast_java.h"
 #include "generate_java.h"
 #include "logging.h"
 #include "options.h"
+#include "parser.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -441,6 +443,101 @@
   return decl;
 }
 
+// Visitor for the permission declared in the @Enforce annotation.
+// The visitor pattern evaluates one node at a time, recursive evaluations should be dispatched
+// by creating a new instance of the visitor. Visit methods should use SetResult to return their
+// current value. For example:
+//
+//   Visit(const perm::Expression& permissionExpression) {
+//     std::shared_ptr<Expression> expr = Evaluate(permissionExpression.FirstChild());
+//     ...
+//     SetResult(TRUE_VALUE);
+//   }
+class PermissionVisitor : public perm::Visitor {
+ public:
+  // Converts a permission expression (e.g., "permission = CALL_PHONE") into an equivalent Java
+  // expression (e.g., "(checkPermission("CALL_PHONE", ...) == GRANTED").
+  static std::shared_ptr<Expression> Evaluate(const perm::Expression& expr) {
+    PermissionVisitor visitor;
+    expr.DispatchVisit(visitor);
+    return visitor.GetResult();
+  }
+
+ private:
+  void Visit(const perm::AndQuantifier& quantifier) {
+    std::shared_ptr<Expression> result;
+    for (const auto& operand : quantifier.GetOperands()) {
+      auto expr = Evaluate(*operand);
+      if (result) {
+        result = std::make_shared<Comparison>(result, "&&", expr);
+      } else {
+        result = expr;
+      }
+    }
+    SetResult(result);
+  }
+
+  void Visit(const perm::OrQuantifier& quantifier) {
+    std::shared_ptr<Expression> result;
+    for (const auto& operand : quantifier.GetOperands()) {
+      auto expr = Evaluate(*operand);
+      if (result) {
+        result = std::make_shared<Comparison>(result, "||", expr);
+      } else {
+        result = expr;
+      }
+    }
+    SetResult(result);
+  }
+
+  void Visit(const perm::Predicate& p) {
+    switch (p.GetType()) {
+      case perm::Predicate::Type::kPermission: {
+        auto permissionGranted = std::make_shared<LiteralExpression>(
+            "android.content.pm.PackageManager.PERMISSION_GRANTED");
+        auto checkPermission = std::make_shared<MethodCall>(
+            std::make_shared<LiteralExpression>("android.permission.PermissionManager"),
+            "checkPermission",
+            std::vector<std::shared_ptr<Expression>>{
+                std::make_shared<LiteralExpression>("android.Manifest.permission." + p.GetValue()),
+                std::make_shared<MethodCall>(THIS_VALUE, "getCallingPid"),
+                std::make_shared<MethodCall>(THIS_VALUE, "getCallingUid")});
+        SetResult(std::make_shared<Comparison>(checkPermission, "==", permissionGranted));
+        break;
+      }
+      case perm::Predicate::Type::kUid: {
+        auto uid = std::make_shared<LiteralExpression>("android.os.Process." + p.GetValue());
+        auto getCallingUid = std::make_shared<MethodCall>(THIS_VALUE, "getCallingUid");
+        SetResult(std::make_shared<Comparison>(getCallingUid, "==", uid));
+        break;
+      }
+      default: {
+        AIDL_FATAL(AIDL_LOCATION_HERE) << "Unsupported predicate: " << p.ToString();
+        break;
+      }
+    }
+  }
+
+  std::shared_ptr<Expression> GetResult() { return result_; }
+  void SetResult(std::shared_ptr<Expression> expr) { result_ = expr; }
+  std::shared_ptr<Expression> result_;
+};
+
+static void generate_permission_checks(const AidlMethod& method,
+                                       std::shared_ptr<StatementBlock> addTo) {
+  auto expr = method.GetType().EnforceExpression(method);
+  if (expr) {
+    auto ifstatement = std::make_shared<IfStatement>();
+    auto permissionExpression = PermissionVisitor::Evaluate(*expr.get());
+    ifstatement->expression = std::make_shared<Comparison>(permissionExpression, "!=", TRUE_VALUE);
+    ifstatement->statements = std::make_shared<StatementBlock>();
+    ifstatement->statements->Add(std::make_shared<LiteralStatement>(android::base::StringPrintf(
+        "throw new SecurityException(\"Access denied, requires: %s\");\n",
+        expr->ToString().c_str())));
+    addTo->Add(ifstatement);
+  }
+}
+
 static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
                                std::shared_ptr<Variable> transact_data,
                                std::shared_ptr<Variable> transact_reply,
@@ -468,6 +565,8 @@
             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
   }
 
+  generate_permission_checks(method, statements);
+
   auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
 
   // args