no setters for @JavaOnlyImmutable union

AIDL compiler doesn't generate setters for a union-generated class when
a union is annotated @JavaOnlyImmutable.

Bug: 171637180
Test: aidl_unittests & aidl_integration_test
Change-Id: Id8290cf86f2ba5e593c930727a3741273e615ff0
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index d55460f..3635ad2 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -3189,16 +3189,18 @@
   private Object _value;
 
   public Foo() {
-    int[] value = {42};
-    _set(ns, value);
+    int[] _value = {42};
+    this._tag = ns;
+    this._value = _value;
   }
 
   private Foo(android.os.Parcel _aidl_parcel) {
     readFromParcel(_aidl_parcel);
   }
 
-  private Foo(int tag, Object value) {
-    _set(tag, value);
+  private Foo(int _tag, Object _value) {
+    this._tag = _tag;
+    this._value = _value;
   }
 
   public int getTag() {
@@ -3344,9 +3346,9 @@
     throw new IllegalStateException("unknown field: " + _tag);
   }
 
-  private void _set(int tag, Object value) {
-    this._tag = tag;
-    this._value = value;
+  private void _set(int _tag, Object _value) {
+    this._tag = _tag;
+    this._value = _value;
   }
 }
 )";
diff --git a/generate_java.cpp b/generate_java.cpp
index 069a20d..3ee3b3a 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -642,8 +642,6 @@
   const string tag_type = "int";
   const AidlTypeSpecifier tag_type_specifier(AIDL_LOCATION_HERE, tag_type, false /* isArray */,
                                              nullptr /* type_params */, "");
-  const string tag_name = "_tag";
-  const string value_name = "_value";
   const string clazz = decl->GetName();
 
   out << "/*\n";
@@ -669,8 +667,9 @@
   }
   out << "\n";
 
-  out << "private " + tag_type + " " + tag_name + ";\n";
-  out << "private Object " + value_name + ";\n";
+  const auto final_opt = decl->IsJavaOnlyImmutable() ? "final " : "";
+  out << "private " << final_opt << tag_type + " _tag;\n";
+  out << "private " << final_opt << "Object _value;\n";
   out << "\n";
 
   AIDL_FATAL_IF(decl->GetFields().empty(), *decl) << "Union '" << clazz << "' is empty.";
@@ -681,27 +680,35 @@
   // default ctor() inits with first member's default value
   out << "public " + clazz + "() {\n";
   out.Indent();
-  out << first_type + " value = " << (first_value.empty() ? "null" : first_value) << ";\n";
-  out << "_set(" + first_field->GetName() + ", value);\n";
+  out << first_type + " _value = " << (first_value.empty() ? "null" : first_value) << ";\n";
+  out << "this._tag = " << first_field->GetName() << ";\n";
+  out << "this._value = _value;\n";
   out.Dedent();
   out << "}\n\n";
 
-  // ctor(Parcel)
-  out << "private " + clazz + "(android.os.Parcel _aidl_parcel) {\n";
-  out << "  readFromParcel(_aidl_parcel);\n";
-  out << "}\n\n";
+  if (!decl->IsJavaOnlyImmutable()) {
+    // private ctor(Parcel)
+    out << "private " + clazz + "(android.os.Parcel _aidl_parcel) {\n";
+    out << "  readFromParcel(_aidl_parcel);\n";
+    out << "}\n\n";
+  }
 
-  // ctor(tag, value)
-  out << "private " + clazz + "(" + tag_type + " tag, Object value) {\n";
-  out << "  _set(tag, value);\n";
+  // private ctor(tag, value)
+  out << "private " + clazz + "(" + tag_type + " _tag, Object _value) {\n";
+  out.Indent();
+  out << "this._tag = _tag;\n";
+  out << "this._value = _value;\n";
+  out.Dedent();
   out << "}\n\n";
 
   // getTag()
   out << "public " + tag_type + " " + "getTag() {\n";
-  out << "  return " + tag_name + ";\n";
+  out.Indent();
+  out << "return _tag;\n";
+  out.Dedent();
   out << "}\n\n";
 
-  // value ctor, getter, setter for each field
+  // value ctor, getter, setter(for mutable) for each field
   for (const auto& variable : decl->GetFields()) {
     auto var_name = variable->GetName();
     auto var_type = JavaSignatureOf(variable->GetType(), typenames);
@@ -709,8 +716,10 @@
     out << "// " + variable->Signature() + ";\n";
     // value ctor
     out << variable->GetType().GetComments() + "\n";
-    out << "public static " + clazz + " " + var_name + "(" + var_type + " " + value_name + ") {\n";
-    out << "  return new " + clazz + "(" + var_name + ", " + value_name + ");\n";
+    out << "public static " + clazz + " " + var_name + "(" + var_type + " _value) {\n";
+    out.Indent();
+    out << "return new " + clazz + "(" + var_name + ", _value);\n";
+    out.Dedent();
     out << "}\n\n";
 
     // getter
@@ -718,14 +727,20 @@
       out << "@SuppressWarnings(\"unchecked\")\n";
     }
     out << "public " + var_type + " " + getter_name(*variable) + "() {\n";
-    out << "  _assertTag(" + var_name + ");\n";
-    out << "  return (" + var_type + ") " + value_name + ";\n";
+    out.Indent();
+    out << "_assertTag(" + var_name + ");\n";
+    out << "return (" + var_type + ") _value;\n";
+    out.Dedent();
     out << "}\n\n";
 
     // setter
-    out << "public void " + setter_name(*variable) + "(" + var_type + " " + value_name + ") {\n";
-    out << "  _set(" + var_name + ", " + value_name + ");\n";
-    out << "}\n\n";
+    if (!decl->IsJavaOnlyImmutable()) {
+      out << "public void " + setter_name(*variable) + "(" + var_type + " _value) {\n";
+      out.Indent();
+      out << "_set(" + var_name + ", _value);\n";
+      out.Dedent();
+      out << "}\n\n";
+    }
   }
 
   if (decl->IsVintfStability()) {
@@ -739,7 +754,11 @@
       << "new android.os.Parcelable.Creator<" << clazz << ">() {\n";
   out << "  @Override\n";
   out << "  public " << clazz << " createFromParcel(android.os.Parcel _aidl_source) {\n";
-  out << "    return new " << clazz << "(_aidl_source);\n";
+  if (decl->IsJavaOnlyImmutable()) {
+    out << "    return internalCreateFromParcel(_aidl_source);\n";
+  } else {
+    out << "    return new " + clazz + "(_aidl_source);\n";
+  }
   out << "  }\n";
   out << "  @Override\n";
   out << "  public " << clazz << "[] newArray(int _aidl_size) {\n";
@@ -766,8 +785,8 @@
   out << "@Override\n";
   out << "public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {\n";
   out.Indent();
-  out << write_to_parcel(tag_type_specifier, tag_name, "_aidl_parcel");
-  out << "switch (" + tag_name + ") {\n";
+  out << write_to_parcel(tag_type_specifier, "_tag", "_aidl_parcel");
+  out << "switch (_tag) {\n";
   for (const auto& variable : decl->GetFields()) {
     out << "case " + variable->GetName() + ":\n";
     out.Indent();
@@ -798,8 +817,14 @@
     return code;
   };
 
-  // Not override, but as a user-defined parcelable, this method should be public
-  out << "public void readFromParcel(android.os.Parcel _aidl_parcel) {\n";
+  if (decl->IsJavaOnlyImmutable()) {
+    // When it's immutable we don't need readFromParcel, but we can use it from createFromParcel
+    out << "private static " + clazz +
+               " internalCreateFromParcel(android.os.Parcel _aidl_parcel) {\n";
+  } else {
+    // Not override, but as a user-defined parcelable, this method should be public
+    out << "public void readFromParcel(android.os.Parcel _aidl_parcel) {\n";
+  }
   out.Indent();
   out << tag_type + " _aidl_tag;\n";
   out << read_from_parcel(tag_type_specifier, "_aidl_tag", "_aidl_parcel");
@@ -811,8 +836,12 @@
     out.Indent();
     out << var_type + " _aidl_value;\n";
     out << read_from_parcel(variable->GetType(), "_aidl_value", "_aidl_parcel");
-    out << "_set(_aidl_tag, _aidl_value);\n";
-    out << "return; }\n";
+    if (decl->IsJavaOnlyImmutable()) {
+      out << "return new " << clazz << "(_aidl_tag, _aidl_value); }\n";
+    } else {
+      out << "_set(_aidl_tag, _aidl_value);\n";
+      out << "return; }\n";
+    }
     out.Dedent();
   }
   out << "}\n";
@@ -833,22 +862,26 @@
   out << "}\n\n";
 
   // helper: _tagString
-  out << "private String _tagString(" + tag_type + " " + tag_name + ") {\n";
-  out << "  switch (" + tag_name + ") {\n";
+  out << "private String _tagString(" + tag_type + " _tag) {\n";
+  out << "  switch (_tag) {\n";
   for (const auto& variable : decl->GetFields()) {
     auto var_name = variable->GetName();
     out << "  case " + var_name + ": return \"" + var_name + "\";\n";
   }
   out << "  }\n";
-  out << "  throw new IllegalStateException(\"unknown field: \" + " + tag_name + ");\n";
-  out << "}\n\n";
-
-  // helper: _set
-  out << "private void _set(" + tag_type + " tag, Object value) {\n";
-  out << "  this." + tag_name + " = tag;\n";
-  out << "  this." + value_name + " = value;\n";
+  out << "  throw new IllegalStateException(\"unknown field: \" + _tag);\n";
   out << "}\n";
 
+  if (!decl->IsJavaOnlyImmutable()) {
+    out << "\n";
+    out << "private void _set(int _tag, Object _value) {\n";
+    out.Indent();
+    out << "this._tag = _tag;\n";
+    out << "this._value = _value;\n";
+    out.Dedent();
+    out << "}\n";
+  }
+
   out.Dedent();
   out << "}\n";
 }