Loading cmds/installd/InstalldNativeService.cpp +17 −14 Original line number Diff line number Diff line Loading @@ -915,15 +915,8 @@ binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std: return res; } /* Try to ensure free_size bytes of storage are available. * Returns 0 on success. * This is rather simple-minded because doing a full LRU would * be potentially memory-intensive, and without atime it would * also require that apps constantly modify file metadata even * when just reading from the cache, which is pretty awful. */ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize, int32_t flags) { int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); std::lock_guard<std::recursive_mutex> lock(mLock); Loading @@ -938,11 +931,12 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin return error("Failed to determine free space for " + data_path); } int64_t needed = freeStorageSize - free; int64_t cleared = 0; int64_t needed = targetFreeBytes - free; LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested " << freeStorageSize << "; needed " << needed; << targetFreeBytes << "; needed " << needed; if (free >= freeStorageSize) { if (free >= targetFreeBytes) { return ok(); } Loading Loading @@ -999,6 +993,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin // 2. Populate tracker stats and insert into priority queue ATRACE_BEGIN("populate"); int64_t cacheTotal = 0; auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) { return (left->getCacheRatio() < right->getCacheRatio()); }; Loading @@ -1007,6 +1002,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin for (const auto& it : trackers) { it.second->loadStats(); queue.push(it.second); cacheTotal += it.second->cacheUsed; } ATRACE_END(); Loading @@ -1023,6 +1019,12 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin break; } // Only keep clearing when we haven't pushed into reserved area if (cacheReservedBytes > 0 && cleared >= (cacheTotal - cacheReservedBytes)) { LOG(DEBUG) << "Refusing to clear cached data in reserved space"; break; } // Find the best tracker to work with; this might involve swapping // if the active tracker is no longer the most over quota bool nextBetter = active && !queue.empty() Loading Loading @@ -1052,13 +1054,14 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin } active->cacheUsed -= item->size; needed -= item->size; 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 = freeStorageSize - free; needed = targetFreeBytes - free; if (needed <= 0) { break; } else { Loading @@ -1073,11 +1076,11 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin } free = data_disk_free(data_path); if (free >= freeStorageSize) { if (free >= targetFreeBytes) { return ok(); } else { return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64, freeStorageSize, data_path.c_str(), free)); targetFreeBytes, data_path.c_str(), free)); } } Loading cmds/installd/InstalldNativeService.h +2 −2 Original line number Diff line number Diff line Loading @@ -101,8 +101,8 @@ public: binder::Status removeIdmap(const std::string& overlayApkPath); binder::Status rmPackageDir(const std::string& packageDir); binder::Status markBootComplete(const std::string& instructionSet); binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize, int32_t flags); binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags); binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid, const std::string& packageName, const std::string& nativeLibPath32, int32_t userId); binder::Status createOatDir(const std::string& oatDir, const std::string& instructionSet); Loading cmds/installd/binder/android/os/IInstalld.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,8 @@ interface IInstalld { void removeIdmap(@utf8InCpp String overlayApkPath); void rmPackageDir(@utf8InCpp String packageDir); void markBootComplete(@utf8InCpp String instructionSet); void freeCache(@nullable @utf8InCpp String uuid, long freeStorageSize, int flags); void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes, long cacheReservedBytes, int flags); void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, @utf8InCpp String nativeLibPath32, int userId); void createOatDir(@utf8InCpp String oatDir, @utf8InCpp String instructionSet); Loading cmds/installd/tests/installd_cache_test.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -146,7 +146,7 @@ TEST_F(CacheTest, FreeCache_All) { EXPECT_EQ(0, exists("com.example/cache/foo/one")); EXPECT_EQ(0, exists("com.example/cache/foo/two")); service->freeCache(testUuid, kTbInBytes, service->freeCache(testUuid, kTbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(0, exists("com.example/normal")); Loading @@ -163,13 +163,13 @@ TEST_F(CacheTest, FreeCache_Age) { touch("com.example/cache/foo/one", kMbInBytes, 60); touch("com.example/cache/foo/two", kMbInBytes, 120); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/one")); EXPECT_EQ(0, exists("com.example/cache/foo/two")); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/one")); Loading Loading @@ -197,7 +197,7 @@ TEST_F(CacheTest, FreeCache_Tombstone) { EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar1")); EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar2")); service->freeCache(testUuid, kTbInBytes, service->freeCache(testUuid, kTbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/foo1")); Loading @@ -219,7 +219,7 @@ TEST_F(CacheTest, FreeCache_Group) { setxattr("com.example/cache/foo", "user.cache_group"); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/foo1")); Loading Loading @@ -264,7 +264,7 @@ TEST_F(CacheTest, FreeCache_GroupTombstone) { setxattr("com.example/cache/tomb", "user.cache_tombstone"); setxattr("com.example/cache/tomb/group", "user.cache_group"); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(kMbInBytes, size("com.example/cache/group/file1")); Loading @@ -285,7 +285,7 @@ TEST_F(CacheTest, FreeCache_GroupTombstone) { EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1")); EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2")); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, size("com.example/cache/group/file1")); Loading @@ -306,7 +306,7 @@ TEST_F(CacheTest, FreeCache_GroupTombstone) { EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1")); EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2")); service->freeCache(testUuid, kTbInBytes, service->freeCache(testUuid, kTbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, size("com.example/cache/group/file1")); Loading Loading
cmds/installd/InstalldNativeService.cpp +17 −14 Original line number Diff line number Diff line Loading @@ -915,15 +915,8 @@ binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std: return res; } /* Try to ensure free_size bytes of storage are available. * Returns 0 on success. * This is rather simple-minded because doing a full LRU would * be potentially memory-intensive, and without atime it would * also require that apps constantly modify file metadata even * when just reading from the cache, which is pretty awful. */ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize, int32_t flags) { int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); std::lock_guard<std::recursive_mutex> lock(mLock); Loading @@ -938,11 +931,12 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin return error("Failed to determine free space for " + data_path); } int64_t needed = freeStorageSize - free; int64_t cleared = 0; int64_t needed = targetFreeBytes - free; LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested " << freeStorageSize << "; needed " << needed; << targetFreeBytes << "; needed " << needed; if (free >= freeStorageSize) { if (free >= targetFreeBytes) { return ok(); } Loading Loading @@ -999,6 +993,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin // 2. Populate tracker stats and insert into priority queue ATRACE_BEGIN("populate"); int64_t cacheTotal = 0; auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) { return (left->getCacheRatio() < right->getCacheRatio()); }; Loading @@ -1007,6 +1002,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin for (const auto& it : trackers) { it.second->loadStats(); queue.push(it.second); cacheTotal += it.second->cacheUsed; } ATRACE_END(); Loading @@ -1023,6 +1019,12 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin break; } // Only keep clearing when we haven't pushed into reserved area if (cacheReservedBytes > 0 && cleared >= (cacheTotal - cacheReservedBytes)) { LOG(DEBUG) << "Refusing to clear cached data in reserved space"; break; } // Find the best tracker to work with; this might involve swapping // if the active tracker is no longer the most over quota bool nextBetter = active && !queue.empty() Loading Loading @@ -1052,13 +1054,14 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin } active->cacheUsed -= item->size; needed -= item->size; 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 = freeStorageSize - free; needed = targetFreeBytes - free; if (needed <= 0) { break; } else { Loading @@ -1073,11 +1076,11 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin } free = data_disk_free(data_path); if (free >= freeStorageSize) { if (free >= targetFreeBytes) { return ok(); } else { return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64, freeStorageSize, data_path.c_str(), free)); targetFreeBytes, data_path.c_str(), free)); } } Loading
cmds/installd/InstalldNativeService.h +2 −2 Original line number Diff line number Diff line Loading @@ -101,8 +101,8 @@ public: binder::Status removeIdmap(const std::string& overlayApkPath); binder::Status rmPackageDir(const std::string& packageDir); binder::Status markBootComplete(const std::string& instructionSet); binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize, int32_t flags); binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags); binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid, const std::string& packageName, const std::string& nativeLibPath32, int32_t userId); binder::Status createOatDir(const std::string& oatDir, const std::string& instructionSet); Loading
cmds/installd/binder/android/os/IInstalld.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,8 @@ interface IInstalld { void removeIdmap(@utf8InCpp String overlayApkPath); void rmPackageDir(@utf8InCpp String packageDir); void markBootComplete(@utf8InCpp String instructionSet); void freeCache(@nullable @utf8InCpp String uuid, long freeStorageSize, int flags); void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes, long cacheReservedBytes, int flags); void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, @utf8InCpp String nativeLibPath32, int userId); void createOatDir(@utf8InCpp String oatDir, @utf8InCpp String instructionSet); Loading
cmds/installd/tests/installd_cache_test.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -146,7 +146,7 @@ TEST_F(CacheTest, FreeCache_All) { EXPECT_EQ(0, exists("com.example/cache/foo/one")); EXPECT_EQ(0, exists("com.example/cache/foo/two")); service->freeCache(testUuid, kTbInBytes, service->freeCache(testUuid, kTbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(0, exists("com.example/normal")); Loading @@ -163,13 +163,13 @@ TEST_F(CacheTest, FreeCache_Age) { touch("com.example/cache/foo/one", kMbInBytes, 60); touch("com.example/cache/foo/two", kMbInBytes, 120); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/one")); EXPECT_EQ(0, exists("com.example/cache/foo/two")); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/one")); Loading Loading @@ -197,7 +197,7 @@ TEST_F(CacheTest, FreeCache_Tombstone) { EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar1")); EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar2")); service->freeCache(testUuid, kTbInBytes, service->freeCache(testUuid, kTbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/foo1")); Loading @@ -219,7 +219,7 @@ TEST_F(CacheTest, FreeCache_Group) { setxattr("com.example/cache/foo", "user.cache_group"); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, exists("com.example/cache/foo/foo1")); Loading Loading @@ -264,7 +264,7 @@ TEST_F(CacheTest, FreeCache_GroupTombstone) { setxattr("com.example/cache/tomb", "user.cache_tombstone"); setxattr("com.example/cache/tomb/group", "user.cache_group"); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(kMbInBytes, size("com.example/cache/group/file1")); Loading @@ -285,7 +285,7 @@ TEST_F(CacheTest, FreeCache_GroupTombstone) { EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1")); EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2")); service->freeCache(testUuid, free() + kKbInBytes, service->freeCache(testUuid, free() + kKbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, size("com.example/cache/group/file1")); Loading @@ -306,7 +306,7 @@ TEST_F(CacheTest, FreeCache_GroupTombstone) { EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1")); EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2")); service->freeCache(testUuid, kTbInBytes, service->freeCache(testUuid, kTbInBytes, 0, FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA); EXPECT_EQ(-1, size("com.example/cache/group/file1")); Loading