Merge "Periodically free cache below high storage threshold"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index d4c17fe..289c2ae 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1602,6 +1602,7 @@
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
auto data_path = create_data_path(uuid_);
auto noop = (flags & FLAG_FREE_CACHE_NOOP);
+ auto defy_target = (flags & FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES);
int64_t free = data_disk_free(data_path);
if (free < 0) {
@@ -1610,11 +1611,13 @@
int64_t cleared = 0;
int64_t needed = targetFreeBytes - free;
- LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
- << targetFreeBytes << "; needed " << needed;
+ if (!defy_target) {
+ LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
+ << targetFreeBytes << "; needed " << needed;
- if (free >= targetFreeBytes) {
- return ok();
+ if (free >= targetFreeBytes) {
+ return ok();
+ }
}
if (flags & FLAG_FREE_CACHE_V2) {
@@ -1739,15 +1742,17 @@
cleared += item->size;
}
- // Verify that we're actually done before bailing, since sneaky
- // apps might be using hardlinks
- if (needed <= 0) {
- free = data_disk_free(data_path);
- needed = targetFreeBytes - free;
+ if (!defy_target) {
+ // Verify that we're actually done before bailing, since sneaky
+ // apps might be using hardlinks
if (needed <= 0) {
- break;
- } else {
- LOG(WARNING) << "Expected to be done but still need " << needed;
+ free = data_disk_free(data_path);
+ needed = targetFreeBytes - free;
+ if (needed <= 0) {
+ break;
+ } else {
+ LOG(WARNING) << "Expected to be done but still need " << needed;
+ }
}
}
}
@@ -1757,12 +1762,16 @@
return error("Legacy cache logic no longer supported");
}
- free = data_disk_free(data_path);
- if (free >= targetFreeBytes) {
- return ok();
+ if (!defy_target) {
+ free = data_disk_free(data_path);
+ if (free >= targetFreeBytes) {
+ return ok();
+ } else {
+ return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64,
+ targetFreeBytes, data_path.c_str(), free));
+ }
} else {
- return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64,
- targetFreeBytes, data_path.c_str(), free));
+ return ok();
}
}
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index e024548..684a311 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -140,6 +140,8 @@
const int FLAG_FREE_CACHE_V2 = 0x100;
const int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 0x200;
const int FLAG_FREE_CACHE_NOOP = 0x400;
+ // Set below flag to clear cache irrespective of target free bytes required
+ const int FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES = 0x800;
const int FLAG_USE_QUOTA = 0x1000;
const int FLAG_FORCE = 0x2000;
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 8a27a06..4976646 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -42,6 +42,7 @@
#define FLAG_FREE_CACHE_V2 InstalldNativeService::FLAG_FREE_CACHE_V2
#define FLAG_FREE_CACHE_V2_DEFY_QUOTA InstalldNativeService::FLAG_FREE_CACHE_V2_DEFY_QUOTA
+#define FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES InstalldNativeService::FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES
int get_property(const char *key, char *value, const char *default_value) {
return property_get(key, value, default_value);
@@ -181,6 +182,35 @@
EXPECT_EQ(0, exists("com.example/cache/foo/two"));
}
+TEST_F(CacheTest, FreeCache_DefyTargetFreeBytes) {
+ LOG(INFO) << "FreeCache_DefyTargetFreeBytes";
+
+ mkdir("com.example");
+ touch("com.example/normal", 1 * kMbInBytes, 60);
+ mkdir("com.example/cache");
+ mkdir("com.example/cache/foo");
+ touch("com.example/cache/foo/one", 65 * kMbInBytes, 60);
+ touch("com.example/cache/foo/two", 2 * kMbInBytes, 120);
+
+ EXPECT_EQ(0, exists("com.example/normal"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/one"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/two"));
+
+ service->freeCache(testUuid, kMbInBytes, FLAG_FREE_CACHE_V2
+ | FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES);
+
+ EXPECT_EQ(0, exists("com.example/normal"));
+ EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/two"));
+
+ service->freeCache(testUuid, kMbInBytes, FLAG_FREE_CACHE_V2
+ | FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES);
+
+ EXPECT_EQ(0, exists("com.example/normal"));
+ EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/two"));
+}
+
TEST_F(CacheTest, FreeCache_Age) {
LOG(INFO) << "FreeCache_Age";