summaryrefslogtreecommitdiff
path: root/libs/androidfw
diff options
context:
space:
mode:
Diffstat (limited to 'libs/androidfw')
-rw-r--r--libs/androidfw/ApkAssets.cpp5
-rw-r--r--libs/androidfw/Idmap.cpp20
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h18
-rw-r--r--libs/androidfw/tests/Idmap_test.cpp30
4 files changed, 61 insertions, 12 deletions
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 918e7af12d31..05f4d6b63a4c 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -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
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 0b2fd9ec982d..eb6ee9525bb9 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -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
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index ccb57f373473..ecc1ce65d124 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -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,
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 41ba637da5d7..7aa0dbbafab3 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -38,7 +38,7 @@ class IdmapTest : public ::testing::Test {
protected:
void SetUp() override {
// Move to the test data directory so the idmap can locate the overlay APK.
- std::string original_path = base::GetExecutableDirectory();
+ original_path = base::GetExecutableDirectory();
chdir(GetTestDataPath().c_str());
system_assets_ = ApkAssets::Load("system/system.apk");
@@ -49,10 +49,14 @@ class IdmapTest : public ::testing::Test {
overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
ASSERT_NE(nullptr, overlayable_assets_);
+ }
+
+ void TearDown() override {
chdir(original_path.c_str());
}
protected:
+ std::string original_path;
std::unique_ptr<const ApkAssets> system_assets_;
std::unique_ptr<const ApkAssets> overlay_assets_;
std::unique_ptr<const ApkAssets> overlayable_assets_;
@@ -221,8 +225,7 @@ TEST_F(IdmapTest, OverlaidResourceHasSameName) {
TEST_F(IdmapTest, OverlayLoaderInterop) {
std::string contents;
- auto loader_assets = ApkAssets::LoadTable(GetTestDataPath() + "/loader/resources.arsc",
- PROPERTY_LOADER);
+ auto loader_assets = ApkAssets::LoadTable("loader/resources.arsc", PROPERTY_LOADER);
AssetManager2 asset_manager;
asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(),
@@ -241,4 +244,25 @@ TEST_F(IdmapTest, OverlayLoaderInterop) {
ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader");
}
+TEST_F(IdmapTest, OverlayAssetsIsUpToDate) {
+ std::string idmap_contents;
+ ASSERT_TRUE(base::ReadFileToString("overlay/overlay.idmap", &idmap_contents));
+
+ TemporaryFile temp_file;
+ ASSERT_TRUE(base::WriteStringToFile(idmap_contents, temp_file.path));
+
+ auto apk_assets = ApkAssets::LoadOverlay(temp_file.path);
+ ASSERT_NE(nullptr, apk_assets);
+ ASSERT_TRUE(apk_assets->IsUpToDate());
+
+ unlink(temp_file.path);
+ ASSERT_FALSE(apk_assets->IsUpToDate());
+ sleep(2);
+
+ base::WriteStringToFile("hello", temp_file.path);
+ sleep(2);
+
+ ASSERT_FALSE(apk_assets->IsUpToDate());
+}
+
} // namespace