Snap for 9560500 from 434cb410c4243a8fc18d0ba0b41276794bb53967 to sdk-release

Change-Id: Ia58d4b32cde7e1b7bac784650ef6f2f41e8faf95
diff --git a/aidl_dumpapi.cpp b/aidl_dumpapi.cpp
index df5be2f..5162021 100644
--- a/aidl_dumpapi.cpp
+++ b/aidl_dumpapi.cpp
@@ -31,6 +31,23 @@
 namespace android {
 namespace aidl {
 
+static bool NeedsFinalValue(const AidlTypeSpecifier& type, const AidlConstantValue& c) {
+  // For enum types, use enumerator
+  if (auto defined_type = type.GetDefinedType();
+      defined_type && defined_type->AsEnumDeclaration()) {
+    return false;
+  }
+  // We need final value for constant expression which is not a single constant expression.
+  struct Visitor : AidlVisitor {
+    bool trivial = true;
+    void Visit(const AidlConstantReference&) override { trivial = false; }
+    void Visit(const AidlUnaryConstExpression&) override { trivial = false; }
+    void Visit(const AidlBinaryConstExpression&) override { trivial = false; }
+  } v;
+  c.DispatchVisit(v);
+  return !v.trivial;
+}
+
 void DumpVisitor::DumpType(const AidlDefinedType& dt, const string& type) {
   if (!dt.IsUserDefined()) {
     return;
@@ -99,8 +116,25 @@
 void DumpVisitor::DumpConstantValue(const AidlTypeSpecifier& type, const AidlConstantValue& c) {
   if (inline_constants) {
     out << c.ValueString(type, AidlConstantValueDecorator);
+    return;
+  }
+  if (c.GetType() == AidlConstantValue::Type::ARRAY) {
+    type.ViewAsArrayBase([&](const auto& base_type) {
+      out << "{";
+      for (size_t i = 0; i < c.Size(); i++) {
+        if (i > 0) {
+          out << ", ";
+        }
+        DumpConstantValue(base_type, c.ValueAt(i));
+      }
+      out << "}";
+    });
   } else {
     c.DispatchVisit(*this);
+    // print final value as comment
+    if (NeedsFinalValue(type, c)) {
+      out << " /* " << c.ValueString(type, AidlConstantValueDecorator) << " */";
+    }
   }
 }
 
diff --git a/aidl_language.h b/aidl_language.h
index e5e9774..3b1c77d 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -696,6 +696,8 @@
     }
   }
   void DispatchVisit(AidlVisitor& visitor) const override { visitor.Visit(*this); }
+  size_t Size() const { return values_.size(); }
+  const AidlConstantValue& ValueAt(size_t index) const { return *values_.at(index); }
 
  private:
   AidlConstantValue(const AidlLocation& location, Type parsed_type, int64_t parsed_value,
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 7dc83aa..cef6152 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -2479,7 +2479,7 @@
   EXPECT_EQ(string(kPreamble).append("package foo.bar;\n"
                                      "enum Enum {\n"
                                      "  FOO,\n"
-                                     "  BAR = (FOO + 1),\n"
+                                     "  BAR = (FOO + 1) /* 1 */,\n"
                                      "}\n"),
             actual);
 }
@@ -2508,7 +2508,7 @@
   EXPECT_EQ(string(kPreamble).append("package foo.bar;\n"
                                      "parcelable Foo {\n"
                                      "  foo.bar.Enum e = foo.bar.Enum.FOO;\n"
-                                     "  int n = foo.bar.Enum.FOO;\n"
+                                     "  int n = foo.bar.Enum.FOO /* 0 */;\n"
                                      "}\n"),
             actual);
 }
@@ -5014,6 +5014,70 @@
             code);
 }
 
+TEST_F(AidlTest, DumpApiWithConstantReferences) {
+  io_delegate_.SetFileContents("foo/bar/Foo.aidl", R"(
+package foo.bar;
+import foo.bar.Bar;
+import foo.bar.Enum;
+parcelable Foo {
+  int n = Bar.A + 1;
+  int[] ns = {1, Bar.A, Bar.B + 1};
+  Enum e = Enum.A;
+  Enum[] es = {Enum.A, Enum.B};
+}
+)");
+  io_delegate_.SetFileContents("foo/bar/Bar.aidl", R"(
+package foo.bar;
+parcelable Bar {
+  const int A = 1;
+  const int B = A + 1;
+}
+)");
+  io_delegate_.SetFileContents("foo/bar/Enum.aidl", R"(
+package foo.bar;
+enum Enum {
+  A,
+  B = A + 2,
+}
+)");
+  vector<string> args = {"aidl",
+                         "--dumpapi",
+                         "--out=dump",
+                         "--include=.",
+                         "foo/bar/Foo.aidl",
+                         "foo/bar/Bar.aidl",
+                         "foo/bar/Enum.aidl"};
+  ASSERT_TRUE(dump_api(Options::From(args), io_delegate_));
+
+  string actual;
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Foo.aidl", &actual));
+  EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
+parcelable Foo {
+  int n = (foo.bar.Bar.A + 1) /* 2 */;
+  int[] ns = {1, foo.bar.Bar.A /* 1 */, (foo.bar.Bar.B + 1) /* 3 */};
+  foo.bar.Enum e = foo.bar.Enum.A;
+  foo.bar.Enum[] es = {foo.bar.Enum.A, foo.bar.Enum.B};
+}
+)"),
+            actual);
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Bar.aidl", &actual));
+  EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
+parcelable Bar {
+  const int A = 1;
+  const int B = (A + 1) /* 2 */;
+}
+)"),
+            actual);
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Enum.aidl", &actual));
+  EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
+enum Enum {
+  A,
+  B = (A + 2) /* 2 */,
+}
+)"),
+            actual);
+}
+
 TEST_F(AidlTest, EnumDefaultShouldBeEnumerators) {
   io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO = 1, BAR = 2}");
   io_delegate_.SetFileContents("a/p/Foo.aidl", R"(