AAPT2: Workaround for findViewById with package ID > 0x7f

The entire View code base checks IDs against View.NO_ID except
findViewById(), which checks to see if the ID is negative.

Any package ID > 0x7f is interpreted as a negative number in Java
(no unsigned ints), so this check prevents the use of IDs > 0x7f.

findViewById is final, so support library workarounds are not possible.

Instead, IDs (@id/foo) are just sentinels, their values don't matter.
If building for pre-O devices, rewrite any references to these IDs of
the for 0xPPTTEEEE, where PP > 7f, to 0x7fPPEEEE.

The symbol table will check for potential collisions against the base
APK, so this should be safe.

Bug: 37498913
Test: manual
Change-Id: Ife3bbd29db287757ef8a2ffd83053d97f1db2613
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 298da4d..bd252d2 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -47,6 +47,7 @@
 }
 
 class ISymbolSource;
+class ISymbolTableDelegate;
 class NameMangler;
 
 class SymbolTable {
@@ -73,7 +74,11 @@
     bool is_public = false;
   };
 
-  SymbolTable(NameMangler* mangler) : mangler_(mangler), cache_(200), id_cache_(200) {}
+  SymbolTable(NameMangler* mangler);
+
+  // Overrides the default ISymbolTableDelegate, which allows a custom defined strategy for
+  // looking up resources from a set of sources.
+  void SetDelegate(std::unique_ptr<ISymbolTableDelegate> delegate);
 
   // Appends a symbol source. The cache is not cleared since entries that
   // have already been found would take precedence due to ordering.
@@ -99,6 +104,7 @@
 
  private:
   NameMangler* mangler_;
+  std::unique_ptr<ISymbolTableDelegate> delegate_;
   std::vector<std::unique_ptr<ISymbolSource>> sources_;
 
   // We use shared_ptr because unique_ptr is not supported and
@@ -109,11 +115,41 @@
   DISALLOW_COPY_AND_ASSIGN(SymbolTable);
 };
 
-/**
- * An interface that a symbol source implements in order to surface symbol
- * information
- * to the symbol table.
- */
+// Allows the customization of the lookup strategy/order of a symbol from a set of
+// symbol sources.
+class ISymbolTableDelegate {
+ public:
+  ISymbolTableDelegate() = default;
+  virtual ~ISymbolTableDelegate() = default;
+
+  // The name is already mangled and does not need further processing.
+  virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
+      const ResourceName& name, const std::vector<std::unique_ptr<ISymbolSource>>& sources) = 0;
+
+  virtual std::unique_ptr<SymbolTable::Symbol> FindById(
+      ResourceId id, const std::vector<std::unique_ptr<ISymbolSource>>& sources) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ISymbolTableDelegate);
+};
+
+class DefaultSymbolTableDelegate : public ISymbolTableDelegate {
+ public:
+  DefaultSymbolTableDelegate() = default;
+  virtual ~DefaultSymbolTableDelegate() = default;
+
+  virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
+      const ResourceName& name,
+      const std::vector<std::unique_ptr<ISymbolSource>>& sources) override;
+  virtual std::unique_ptr<SymbolTable::Symbol> FindById(
+      ResourceId id, const std::vector<std::unique_ptr<ISymbolSource>>& sources) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DefaultSymbolTableDelegate);
+};
+
+// An interface that a symbol source implements in order to surface symbol information
+// to the symbol table.
 class ISymbolSource {
  public:
   virtual ~ISymbolSource() = default;
@@ -122,9 +158,7 @@
       const ResourceName& name) = 0;
   virtual std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) = 0;
 
-  /**
-   * Default implementation tries the name if it exists, else the ID.
-   */
+  // Default implementation tries the name if it exists, else the ID.
   virtual std::unique_ptr<SymbolTable::Symbol> FindByReference(
       const Reference& ref) {
     if (ref.name) {
@@ -136,11 +170,9 @@
   }
 };
 
-/**
- * Exposes the resources in a ResourceTable as symbols for SymbolTable.
- * Instances of this class must outlive the encompassed ResourceTable.
- * Lookups by ID are ignored.
- */
+// Exposes the resources in a ResourceTable as symbols for SymbolTable.
+// Instances of this class must outlive the encompassed ResourceTable.
+// Lookups by ID are ignored.
 class ResourceTableSymbolSource : public ISymbolSource {
  public:
   explicit ResourceTableSymbolSource(ResourceTable* table) : table_(table) {}