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

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

Invalidate idmap when target updates

When the target package update, check if the idmap file must change.
If so, propagate the idmap changes to the targets overlay paths, and
invalidate cached overlay ApkAssets in ResourcesManager.

Bug: 147794117
Bug: 150877400
Test: OverlayRemountedTest
Test: libandroidfw_tests
Change-Id: I6115c30bae3672b188a5ff270720a0eea15b43b5
parent 2d8d9812
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -149,15 +149,21 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
    return error(idmap.GetErrorMessage());
  }

  // idmap files are mapped with mmap in libandroidfw. Deleting and recreating the idmap guarantees
  // that existing memory maps will continue to be valid and unaffected.
  unlink(idmap_path.c_str());

  umask(kIdmapFilePermissionMask);
  std::ofstream fout(idmap_path);
  if (fout.fail()) {
    return error("failed to open idmap path " + idmap_path);
  }

  BinaryStreamVisitor visitor(fout);
  (*idmap)->accept(&visitor);
  fout.close();
  if (fout.fail()) {
    unlink(idmap_path.c_str());
    return error("failed to write to idmap path " + idmap_path);
  }

+2 −2
Original line number Diff line number Diff line
@@ -344,7 +344,7 @@ public class ResourcesManager {
        ApkAssets apkAssets = null;
        if (mLoadedApkAssets != null) {
            apkAssets = mLoadedApkAssets.get(newKey);
            if (apkAssets != null) {
            if (apkAssets != null && apkAssets.isUpToDate()) {
                return apkAssets;
            }
        }
@@ -353,7 +353,7 @@ public class ResourcesManager {
        final WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.get(newKey);
        if (apkAssetsRef != null) {
            apkAssets = apkAssetsRef.get();
            if (apkAssets != null) {
            if (apkAssets != null && apkAssets.isUpToDate()) {
                if (mLoadedApkAssets != null) {
                    mLoadedApkAssets.put(newKey, apkAssets);
                }
+3 −2
Original line number Diff line number Diff line
@@ -385,7 +385,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap
  const StringPiece idmap_data(
      reinterpret_cast<const char*>(idmap_asset->getBuffer(true /*wordAligned*/)),
      static_cast<size_t>(idmap_asset->getLength()));
  std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_data);
  std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_path, idmap_data);
  if (loaded_idmap == nullptr) {
    LOG(ERROR) << "failed to load IDMAP " << idmap_path;
    return {};
@@ -538,8 +538,9 @@ bool ApkAssets::IsUpToDate() const {
    // Loaders are invalidated by the app, not the system, so assume they are up to date.
    return true;
  }
  return (!loaded_idmap_ || loaded_idmap_->IsUpToDate()) &&
      last_mod_time_ == getFileModDate(path_.c_str());

  return last_mod_time_ == getFileModDate(path_.c_str());
}

}  // namespace android
+15 −5
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "androidfw/misc.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
#include "utils/ByteOrder.h"
@@ -192,7 +193,9 @@ static bool IsValidIdmapHeader(const StringPiece& data) {
  return true;
}

LoadedIdmap::LoadedIdmap(const Idmap_header* header,
LoadedIdmap::LoadedIdmap(std::string&& idmap_path,
                         const time_t last_mod_time,
                         const Idmap_header* header,
                         const Idmap_data_header* data_header,
                         const Idmap_target_entry* target_entries,
                         const Idmap_overlay_entry* overlay_entries,
@@ -201,7 +204,9 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header,
       data_header_(data_header),
       target_entries_(target_entries),
       overlay_entries_(overlay_entries),
       string_pool_(string_pool) {
       string_pool_(string_pool),
       idmap_path_(std::move(idmap_path)),
       idmap_last_mod_time_(last_mod_time) {

  size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
                          arraysize(header_->overlay_path));
@@ -212,7 +217,8 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header,
  target_apk_path_.assign(reinterpret_cast<const char*>(header_->target_path), length);
}

std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) {
std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path,
                                                     const StringPiece& idmap_data) {
  ATRACE_CALL();
  if (!IsValidIdmapHeader(idmap_data)) {
    return {};
@@ -275,10 +281,14 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_da

  // Can't use make_unique because LoadedIdmap constructor is private.
  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
      new LoadedIdmap(header, data_header, target_entries, overlay_entries,
                      idmap_string_pool.release()));
      new LoadedIdmap(idmap_path.to_string(), getFileModDate(idmap_path.data()), header,
                      data_header, target_entries, overlay_entries, idmap_string_pool.release()));

  return std::move(loaded_idmap);
}

bool LoadedIdmap::IsUpToDate() const {
  return idmap_last_mod_time_ == getFileModDate(idmap_path_.c_str());
}

}  // namespace android
+16 −2
Original line number Diff line number Diff line
@@ -142,7 +142,13 @@ class IdmapResMap {
class LoadedIdmap {
 public:
  // Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed.
  static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_data);
  static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_path,
                                                 const StringPiece& idmap_data);

  // Returns the path to the IDMAP.
  inline const std::string& IdmapPath() const {
    return idmap_path_;
  }

  // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
  inline const std::string& OverlayApkPath() const {
@@ -167,6 +173,10 @@ class LoadedIdmap {
    return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id);
  }

  // Returns whether the idmap file on disk has not been modified since the construction of this
  // LoadedIdmap.
  bool IsUpToDate() const;

 protected:
  // Exposed as protected so that tests can subclass and mock this class out.
  LoadedIdmap() = default;
@@ -177,13 +187,17 @@ class LoadedIdmap {
  const Idmap_overlay_entry* overlay_entries_;
  const std::unique_ptr<ResStringPool> string_pool_;

  const std::string idmap_path_;
  std::string overlay_apk_path_;
  std::string target_apk_path_;
  const time_t idmap_last_mod_time_;

 private:
  DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);

  explicit LoadedIdmap(const Idmap_header* header,
  explicit LoadedIdmap(std::string&& idmap_path,
                       time_t last_mod_time,
                       const Idmap_header* header,
                       const Idmap_data_header* data_header,
                       const Idmap_target_entry* target_entries,
                       const Idmap_overlay_entry* overlay_entries,
Loading