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) {}