From eb6ab1ec0ae8fc1b574a2baad004ff8de7bc953e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 3 Mar 2021 10:22:54 +0100 Subject: [PATCH] when storage is low, immediately trigger CleanCacheWorker run refs #1869 Script to test this in an emulator with `adb root` in `adb shell`: ```bash cd /data/data/org.fdroid.fdroid.debug/files rm -f fake.apk; touch fake.apk; chown u0_a159.u0_a159 fake.apk ; dd if=/dev/zero of=fake.apk bs=1M count=635; touch -d 2020-02-02 fake.apk ; df -h; ls -lh ``` < --- .../receiver/DeviceStorageReceiver.java | 5 ++--- .../fdroid/fdroid/work/CleanCacheWorker.java | 21 +++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/receiver/DeviceStorageReceiver.java b/app/src/main/java/org/fdroid/fdroid/receiver/DeviceStorageReceiver.java index 08b33d394..7aaa04019 100644 --- a/app/src/main/java/org/fdroid/fdroid/receiver/DeviceStorageReceiver.java +++ b/app/src/main/java/org/fdroid/fdroid/receiver/DeviceStorageReceiver.java @@ -18,9 +18,8 @@ public class DeviceStorageReceiver extends BroadcastReceiver { if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) { int percentageFree = Utils.getPercent(Utils.getImageCacheDirAvailableMemory(context), Utils.getImageCacheDirTotalMemory(context)); - if (percentageFree > 2) { - CleanCacheWorker.schedule(context); - } else { + CleanCacheWorker.force(context); + if (percentageFree <= 2) { DeleteCacheService.deleteAll(context); } } diff --git a/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java b/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java index 022af65b1..f2db0f1d5 100644 --- a/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java +++ b/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java @@ -10,6 +10,8 @@ import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.work.Constraints; import androidx.work.ExistingPeriodicWorkPolicy; +import androidx.work.ExistingWorkPolicy; +import androidx.work.OneTimeWorkRequest; import androidx.work.PeriodicWorkRequest; import androidx.work.WorkManager; import androidx.work.Worker; @@ -42,7 +44,7 @@ public class CleanCacheWorker extends Worker { } /** - * Schedule or cancel a work request to update the app index, according to the + * Schedule or cancel a work request to clean up caches, according to the * current preferences. Should be called a) at boot, b) if the preference * is changed, or c) on startup, in case we get upgraded. */ @@ -68,6 +70,18 @@ public class CleanCacheWorker extends Worker { Utils.debugLog(TAG, "Scheduled periodic work for cleaning the cache."); } + /** + * Force a cache cleanup. Since {@link #deleteOldInstallerFiles(Context)} + * only deletes files older than an hour, any ongoing APK install processes + * should not have their APKs are deleted out from under them. + */ + public static void force(@NonNull final Context context) { + OneTimeWorkRequest cleanCache = new OneTimeWorkRequest.Builder(CleanCacheWorker.class).build(); + WorkManager workManager = WorkManager.getInstance(context); + workManager.enqueueUniqueWork(TAG + ".force", ExistingWorkPolicy.KEEP, cleanCache); + Utils.debugLog(TAG, "Enqueued forced run for cleaning the cache."); + } + @NonNull @Override public Result doWork() { @@ -95,7 +109,10 @@ public class CleanCacheWorker extends Worker { /** * {@link org.fdroid.fdroid.installer.Installer} instances copy the APK into - * a safe place before installing. It doesn't clean up them reliably yet. + * a safe place before installing. This only deletes files older than an + * hour to avoid deleting APKs while they are still being installed. This + * also avoids deleting the nearby swap repo files since that might be + * actively in use. */ private void deleteOldInstallerFiles() { File filesDir = getApplicationContext().getFilesDir();