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

Commit 900b3c21 authored by Nikita Ioffe's avatar Nikita Ioffe
Browse files

installd: clear app's cache before doing a snapshot

Bug: 112431924
Test: installd_service_test
Change-Id: I4a6c3bbf071dcee007e48ece40e5009c1a43ecca
parent 2470dd34
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -766,9 +766,6 @@ static int32_t copy_directory_recursive(const char* from, const char* to) {
    return android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
}

// TODO(narayan): We should pass through the ceDataInode so that we can call
// clearAppData(FLAG_CLEAR_CACHE_ONLY | FLAG_CLEAR_CODE_CACHE before we commence
// the copy.
binder::Status InstalldNativeService::snapshotAppData(
        const std::unique_ptr<std::string>& volumeUuid,
        const std::string& packageName, int32_t user, int32_t storageFlags) {
@@ -813,6 +810,24 @@ binder::Status InstalldNativeService::snapshotAppData(
        return ok();
    }

    // ce_data_inode is not needed when FLAG_CLEAR_CACHE_ONLY is set.
    binder::Status clear_cache_result = clearAppData(volumeUuid, packageName, user,
            storageFlags | FLAG_CLEAR_CACHE_ONLY, 0);
    if (!clear_cache_result.isOk()) {
        // It should be fine to continue snapshot if we for some reason failed
        // to clear cache.
        LOG(WARNING) << "Failed to clear cache of app " << packageName;
    }

    // ce_data_inode is not needed when FLAG_CLEAR_CODE_CACHE_ONLY is set.
    binder::Status clear_code_cache_result = clearAppData(volumeUuid, packageName, user,
            storageFlags | FLAG_CLEAR_CODE_CACHE_ONLY, 0);
    if (!clear_code_cache_result.isOk()) {
        // It should be fine to continue snapshot if we for some reason failed
        // to clear code_cache.
        LOG(WARNING) << "Failed to clear code_cache of app " << packageName;
    }

    if (storageFlags & FLAG_STORAGE_DE) {
        auto from = create_data_user_de_package_path(volume_uuid, user, package_name);
        auto to = create_data_misc_de_rollback_path(volume_uuid, user);
+55 −0
Original line number Diff line number Diff line
@@ -433,6 +433,61 @@ TEST_F(ServiceTest, SnapshotAppData_WrongVolumeUuid) {
          "com.foo", 0, FLAG_STORAGE_DE).isOk());
}

TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsCache) {
  auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
  auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
  auto fake_package_ce_cache_path = read_path_inode(fake_package_ce_path,
      "cache", kXattrInodeCache);
  auto fake_package_ce_code_cache_path = read_path_inode(fake_package_ce_path,
      "code_cache", kXattrInodeCache);
  auto fake_package_de_cache_path = fake_package_de_path + "/cache";
  auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";

  ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
  ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
  ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 700));
  ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 700));
  ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 700));
  ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 700));

  auto deleter = [&fake_package_ce_path, &fake_package_de_path,
          &fake_package_ce_cache_path, &fake_package_ce_code_cache_path,
          &fake_package_de_cache_path, &fake_package_de_code_cache_path]() {
      delete_dir_contents(fake_package_ce_path, true);
      delete_dir_contents(fake_package_de_path, true);
      delete_dir_contents(fake_package_ce_cache_path, true);
      delete_dir_contents(fake_package_ce_code_cache_path, true);
      delete_dir_contents(fake_package_de_cache_path, true);
      delete_dir_contents(fake_package_de_code_cache_path, true);
      rmdir(fake_package_ce_cache_path.c_str());
      rmdir(fake_package_ce_code_cache_path.c_str());
      rmdir(fake_package_de_cache_path.c_str());
      rmdir(fake_package_de_code_cache_path.c_str());
  };
  auto scope_guard = android::base::make_scope_guard(deleter);

  ASSERT_TRUE(android::base::WriteStringToFile(
          "TEST_CONTENT_CE", fake_package_ce_cache_path + "/file1",
          0700, 10000, 20000, false /* follow_symlinks */));
  ASSERT_TRUE(android::base::WriteStringToFile(
          "TEST_CONTENT_CE", fake_package_ce_code_cache_path + "/file1",
          0700, 10000, 20000, false /* follow_symlinks */));
  ASSERT_TRUE(android::base::WriteStringToFile(
          "TEST_CONTENT_DE", fake_package_de_cache_path + "/file1",
          0700, 10000, 20000, false /* follow_symlinks */));
  ASSERT_TRUE(android::base::WriteStringToFile(
          "TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
          0700, 10000, 20000, false /* follow_symlinks */));
  ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
          "com.foo", 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE).isOk());
  // The snapshot call must clear cache.
  struct stat sb;
  ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
  ASSERT_EQ(-1, stat((fake_package_ce_code_cache_path + "/file1").c_str(), &sb));
  ASSERT_EQ(-1, stat((fake_package_de_cache_path + "/file1").c_str(), &sb));
  ASSERT_EQ(-1, stat((fake_package_de_code_cache_path + "/file1").c_str(), &sb));
}

TEST_F(ServiceTest, RestoreAppDataSnapshot) {
  auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
  auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);