AAPT2: Process <java-symbols> and private symbol package

Need to introduce the idea of multiple levels of visibility to support <java-symbol>.

Public, Private, Undefined.

Public means it is accessible from outside and requires an ID assigned.
Private means that we explicitly want this to be a symbol (show up in R.java), but not visible
to other packages. No ID required.

Undefined is any normal resource. When --private-symbols is specified in the link phase,
these resources will not show up in R.java.

Change-Id: Icba89221e08e685dee7683786aa7112baf28c856
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 63629f0..bfef9d0 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -18,10 +18,11 @@
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
-#include "util/Util.h"
 #include "ValueVisitor.h"
 #include "XmlPullParser.h"
 
+#include "util/Util.h"
+
 #include <sstream>
 
 namespace aapt {
@@ -184,7 +185,7 @@
     ResourceName name;
     Source source;
     ResourceId id;
-    bool markPublic = false;
+    SymbolState symbolState = SymbolState::kUndefined;
     std::unique_ptr<Value> value;
     std::list<ParsedResource> childResources;
 };
@@ -192,8 +193,10 @@
 // Recursively adds resources to the ResourceTable.
 static bool addResourcesToTable(ResourceTable* table, const ConfigDescription& config,
                                 IDiagnostics* diag, ParsedResource* res) {
-    if (res->markPublic && !table->markPublic(res->name, res->id, res->source, diag)) {
-        return false;
+    if (res->symbolState != SymbolState::kUndefined) {
+        if (!table->setSymbolState(res->name, res->id, res->source, res->symbolState, diag)) {
+            return false;
+        }
     }
 
     if (!res->value) {
@@ -318,6 +321,8 @@
             result = parseAttr(parser, &parsedResource);
         } else if (elementName == u"public") {
             result = parsePublic(parser, &parsedResource);
+        } else if (elementName == u"java-symbol" || elementName == u"symbol") {
+            result = parseSymbol(parser, &parsedResource);
         } else {
             mDiag->warn(DiagMessage(mSource.withLine(parser->getLineNumber()))
                         << "unknown resource type '" << elementName << "'");
@@ -506,7 +511,29 @@
         outResource->value = util::make_unique<Id>();
     }
 
-    outResource->markPublic = true;
+    outResource->symbolState = SymbolState::kPublic;
+    return true;
+}
+
+bool ResourceParser::parseSymbol(XmlPullParser* parser, ParsedResource* outResource) {
+    const Source source = mSource.withLine(parser->getLineNumber());
+
+    Maybe<StringPiece16> maybeType = findNonEmptyAttribute(parser, u"type");
+    if (!maybeType) {
+        mDiag->error(DiagMessage(source) << "<" << parser->getElementName() << "> must have a "
+                     "'type' attribute");
+        return false;
+    }
+
+    const ResourceType* parsedType = parseResourceType(maybeType.value());
+    if (!parsedType) {
+        mDiag->error(DiagMessage(source) << "invalid resource type '" << maybeType.value()
+                     << "' in <" << parser->getElementName() << ">");
+        return false;
+    }
+
+    outResource->name.type = *parsedType;
+    outResource->symbolState = SymbolState::kPrivate;
     return true;
 }