Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a41e66af authored by Ryan Mitchell's avatar Ryan Mitchell
Browse files

ResXMLTree: Clone DynamicRefTable on creation

XmlBlocks are cached in ResourcesImpl::loadXmlResourceParser(...) and
when asset manager invalidates itself, the references to the dynamic
reference tables point to garbage. Now, the reference table is cloned
when the XmlBlock is created so invalidation will not affect the
XmlTree.

Bug: 74240254
Test: Tested GoogleMaps on 9.75.7 and saw crashes stop
Change-Id: I932db7a85fddc640c4d6ec327f534b5a1ad6d0b1
parent 7692904a
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -1597,7 +1597,8 @@ static volatile int32_t gCount = 0;

ResXMLTree::ResXMLTree(const DynamicRefTable* dynamicRefTable)
    : ResXMLParser(*this)
    , mDynamicRefTable(dynamicRefTable)
    , mDynamicRefTable((dynamicRefTable != nullptr) ? dynamicRefTable->clone()
                                                    : std::unique_ptr<DynamicRefTable>(nullptr))
    , mError(NO_INIT), mOwnedData(NULL)
{
    if (kDebugResXMLTree) {
@@ -1608,7 +1609,7 @@ ResXMLTree::ResXMLTree(const DynamicRefTable* dynamicRefTable)

ResXMLTree::ResXMLTree()
    : ResXMLParser(*this)
    , mDynamicRefTable(NULL)
    , mDynamicRefTable(std::unique_ptr<DynamicRefTable>(nullptr))
    , mError(NO_INIT), mOwnedData(NULL)
{
    if (kDebugResXMLTree) {
@@ -6864,6 +6865,13 @@ DynamicRefTable::DynamicRefTable(uint8_t packageId, bool appAsLib)
    mLookupTable[SYS_PACKAGE_ID] = SYS_PACKAGE_ID;
}

std::unique_ptr<DynamicRefTable> DynamicRefTable::clone() const {
  std::unique_ptr<DynamicRefTable> clone = std::unique_ptr<DynamicRefTable>(
      new DynamicRefTable(mAssignedPackageId, mAppAsLib));
  clone->addMappings(*this);
  return clone;
}

status_t DynamicRefTable::load(const ResTable_lib_header* const header)
{
    const uint32_t entryCount = dtohl(header->count);
@@ -6904,7 +6912,7 @@ status_t DynamicRefTable::addMappings(const DynamicRefTable& other) {
    for (size_t i = 0; i < entryCount; i++) {
        ssize_t index = mEntries.indexOfKey(other.mEntries.keyAt(i));
        if (index < 0) {
            mEntries.add(other.mEntries.keyAt(i), other.mEntries[i]);
            mEntries.add(String16(other.mEntries.keyAt(i)), other.mEntries[i]);
        } else {
            if (other.mEntries[i] != mEntries[index]) {
                return UNKNOWN_ERROR;
+9 −1
Original line number Diff line number Diff line
@@ -799,6 +799,11 @@ class DynamicRefTable;
class ResXMLTree : public ResXMLParser
{
public:
    /**
     * Creates a ResXMLTree with the specified DynamicRefTable for run-time package id translation.
     * The tree stores a clone of the specified DynamicRefTable, so any changes to the original
     * DynamicRefTable will not affect this tree after instantiation.
     **/
    ResXMLTree(const DynamicRefTable* dynamicRefTable);
    ResXMLTree();
    ~ResXMLTree();
@@ -814,7 +819,7 @@ private:

    status_t validateNode(const ResXMLTree_node* node) const;

    const DynamicRefTable* const mDynamicRefTable;
    std::unique_ptr<const DynamicRefTable> mDynamicRefTable;

    status_t                    mError;
    void*                       mOwnedData;
@@ -1655,6 +1660,9 @@ public:

    void addMapping(uint8_t buildPackageId, uint8_t runtimePackageId);

    // Creates a new clone of the reference table
    std::unique_ptr<DynamicRefTable> clone() const;

    // Performs the actual conversion of build-time resource ID to run-time
    // resource ID.
    status_t lookupResourceId(uint32_t* resId) const;