From fc98820c93a75703da9386d5f7dd016eb5913903 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 15 Aug 2016 21:36:33 +0200 Subject: [PATCH] move clearOldFiles() to CleanCacheService to be used on other files Now that there is the ability to remove files based on last access time, it makes sense to use this on all cached files, including icons, etc. --- .../org/fdroid/fdroid/CleanCacheService.java | 48 ++++++++++++++++- .../org/fdroid/fdroid/installer/ApkCache.java | 51 +------------------ ...heTest.java => CleanCacheServiceTest.java} | 9 ++-- 3 files changed, 54 insertions(+), 54 deletions(-) rename app/src/test/java/org/fdroid/fdroid/{installer/ApkCacheTest.java => CleanCacheServiceTest.java} (88%) diff --git a/app/src/main/java/org/fdroid/fdroid/CleanCacheService.java b/app/src/main/java/org/fdroid/fdroid/CleanCacheService.java index d51719917..b912992a9 100644 --- a/app/src/main/java/org/fdroid/fdroid/CleanCacheService.java +++ b/app/src/main/java/org/fdroid/fdroid/CleanCacheService.java @@ -1,12 +1,17 @@ package org.fdroid.fdroid; +import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.IntentService; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Process; import android.os.SystemClock; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import org.apache.commons.io.FileUtils; import org.fdroid.fdroid.installer.ApkCache; @@ -52,7 +57,7 @@ public class CleanCacheService extends IntentService { return; } Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST); - ApkCache.clearApkCache(this); + clearOldFiles(ApkCache.getApkCacheDir(getBaseContext()), Preferences.get().getKeepCacheTime()); deleteStrayIndexFiles(); deleteOldInstallerFiles(); } @@ -111,4 +116,45 @@ public class CleanCacheService extends IntentService { } } } + + /** + * Recursively delete files in {@code dir} that were last used + * {@code secondsAgo} seconds ago. On {@code android-21} and newer, this + * is based on the last access of the file, on older Android versions, it is + * based on the last time the file was modified, e.g. downloaded. + * + * @param dir The directory to recurse in + * @param secondsAgo The number of seconds old that marks a file for deletion. + */ + @TargetApi(21) + public static void clearOldFiles(File dir, long secondsAgo) { + if (dir == null) { + return; + } + File[] files = dir.listFiles(); + if (files == null) { + return; + } + long olderThan = System.currentTimeMillis() - (secondsAgo * 1000L); + for (File f : files) { + if (f.isDirectory()) { + clearOldFiles(f, olderThan); + f.delete(); + } + if (Build.VERSION.SDK_INT < 21) { + if (FileUtils.isFileOlder(f, olderThan)) { + f.delete(); + } + } else { + try { + StructStat stat = Os.lstat(f.getAbsolutePath()); + if (stat.st_atime < olderThan) { + f.delete(); + } + } catch (ErrnoException e) { + e.printStackTrace(); + } + } + } + } } diff --git a/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java b/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java index 587c9c87d..47f6fb32e 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java @@ -26,7 +26,6 @@ import com.nostra13.universalimageloader.utils.StorageUtils; import org.apache.commons.io.FileUtils; import org.fdroid.fdroid.Hasher; -import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.SanitizedFile; @@ -117,19 +116,14 @@ public class ApkCache { } } - public static void clearApkCache(Context context) { - clearOldFiles(getApkCacheDir(context), Preferences.get().getKeepCacheTime()); - } - - /** * This location is only for caching, do not install directly from this location * because if the file is on the External Storage, any other app could swap out * the APK while the install was in process, allowing malware to install things. - * Using {@link Installer#installPackage(Uri localApkUri, Uri downloadUri, String packageName)} + * Using {@link Installer#installPackage(Uri, Uri, Apk)} * is fine since that does the right thing. */ - private static File getApkCacheDir(Context context) { + public static File getApkCacheDir(Context context) { File apkCacheDir = new File(StorageUtils.getCacheDirectory(context, true), CACHE_DIR); if (apkCacheDir.isFile()) { apkCacheDir.delete(); @@ -139,45 +133,4 @@ public class ApkCache { } return apkCacheDir; } - - /** - * Recursively delete files in {@code dir} that were last used - * {@code secondsAgo} seconds ago. On {@code android-21} and newer, this - * is based on the last access of the file, on older Android versions, it is - * based on the last time the file was modified, e.g. downloaded. - * - * @param dir The directory to recurse in - * @param secondsAgo The number of seconds old that marks a file for deletion. - */ - @TargetApi(21) - public static void clearOldFiles(File dir, long secondsAgo) { - if (dir == null) { - return; - } - File[] files = dir.listFiles(); - if (files == null) { - return; - } - long olderThan = System.currentTimeMillis() - (secondsAgo * 1000L); - for (File f : files) { - if (f.isDirectory()) { - clearOldFiles(f, olderThan); - f.delete(); - } - if (Build.VERSION.SDK_INT < 21) { - if (FileUtils.isFileOlder(f, olderThan)) { - f.delete(); - } - } else { - try { - StructStat stat = Os.lstat(f.getAbsolutePath()); - if (stat.st_atime < olderThan) { - f.delete(); - } - } catch (ErrnoException e) { - e.printStackTrace(); - } - } - } - } } diff --git a/app/src/test/java/org/fdroid/fdroid/installer/ApkCacheTest.java b/app/src/test/java/org/fdroid/fdroid/CleanCacheServiceTest.java similarity index 88% rename from app/src/test/java/org/fdroid/fdroid/installer/ApkCacheTest.java rename to app/src/test/java/org/fdroid/fdroid/CleanCacheServiceTest.java index 7d9d26620..8494e6891 100644 --- a/app/src/test/java/org/fdroid/fdroid/installer/ApkCacheTest.java +++ b/app/src/test/java/org/fdroid/fdroid/CleanCacheServiceTest.java @@ -1,7 +1,8 @@ -package org.fdroid.fdroid.installer; +package org.fdroid.fdroid; import org.apache.commons.io.FileUtils; import org.fdroid.fdroid.BuildConfig; +import org.fdroid.fdroid.CleanCacheService; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricGradleTestRunner; @@ -16,7 +17,7 @@ import static org.junit.Assert.assertTrue; // TODO: Use sdk=24 when Robolectric supports this @Config(constants = BuildConfig.class, sdk = 23) @RunWith(RobolectricGradleTestRunner.class) -public class ApkCacheTest { +public class CleanCacheServiceTest { @Test public void testClearOldFiles() throws IOException, InterruptedException { @@ -45,12 +46,12 @@ public class ApkCacheTest { assertTrue(second.createNewFile()); assertTrue(second.exists()); - ApkCache.clearOldFiles(dir, 3); + CleanCacheService.clearOldFiles(dir, 3); assertFalse(first.exists()); assertTrue(second.exists()); Thread.sleep(7000); - ApkCache.clearOldFiles(dir, 3); + CleanCacheService.clearOldFiles(dir, 3); assertFalse(first.exists()); assertFalse(second.exists()); }