From 748352e5a19f023e5289dcb9e5238a0cbf7689ab Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 30 May 2016 23:01:50 +0200 Subject: [PATCH] do not update InstalledAppProvider if already current This adds a check of whether the database has the current APK in it, based on PackageInfo's lastUpdateTime field. This avoids recalculating the hash of the whole APK, which is quite time and resource intensive. --- .../fdroid/fdroid/data/InstalledAppProvider.java | 15 ++++++++++----- .../fdroid/data/InstalledAppProviderService.java | 13 ++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProvider.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProvider.java index 9b3d01877..166d838f0 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProvider.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProvider.java @@ -27,12 +27,12 @@ public class InstalledAppProvider extends FDroidProvider { public static class Helper { /** - * @return The keys are the app ids (package names), and their corresponding values are - * the version code which is installed. + * @return The keys are the package names, and their corresponding values are + * the {@link PackageInfo#lastUpdateTime last update time} in milliseconds. */ - public static Map all(Context context) { + public static Map all(Context context) { - Map cachedInfo = new HashMap<>(); + Map cachedInfo = new HashMap<>(); final Uri uri = InstalledAppProvider.getContentUri(); final String[] projection = InstalledAppProvider.DataColumns.ALL; @@ -43,7 +43,7 @@ public class InstalledAppProvider extends FDroidProvider { while (!cursor.isAfterLast()) { cachedInfo.put( cursor.getString(cursor.getColumnIndex(InstalledAppProvider.DataColumns.PACKAGE_NAME)), - cursor.getInt(cursor.getColumnIndex(InstalledAppProvider.DataColumns.VERSION_CODE)) + cursor.getLong(cursor.getColumnIndex(DataColumns.LAST_UPDATE_TIME)) ); cursor.moveToNext(); } @@ -223,6 +223,11 @@ public class InstalledAppProvider extends FDroidProvider { return getAppUri(values.getAsString(DataColumns.PACKAGE_NAME)); } + /** + * Update is not supported for {@code InstalledAppProvider}. Instead, use + * {@link #insert(Uri, ContentValues)}, and it will overwrite the relevant + * row, if one exists. This just throws {@link UnsupportedOperationException} + */ @Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { throw new UnsupportedOperationException("\"Update' not supported for installed appp provider. Instead, you should insert, and it will overwrite the relevant rows if one exists."); diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java index acd5a8d45..3dc103bac 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -23,7 +23,7 @@ import java.util.concurrent.TimeUnit; * versus what Android says is installed, or processing {@link Intent}s that come * from {@link android.content.BroadcastReceiver}s for {@link Intent#ACTION_PACKAGE_ADDED} * and {@link Intent#ACTION_PACKAGE_REMOVED} - *

+ *

* Since {@link android.content.ContentProvider#insert(Uri, ContentValues)} does not check * for duplicate records, it is entirely the job of this service to ensure that it is not * inserting duplicate versions of the same installed APK. On that note, @@ -94,7 +94,7 @@ public class InstalledAppProviderService extends IntentService { * is in sync with what the {@link PackageManager} tells us is installed. Once * completed, the relevant {@link android.content.ContentProvider}s will be * notified of any changes to installed statuses. - *

+ *

* The installed app cache could get out of sync, e.g. if F-Droid crashed/ or * ran out of battery half way through responding to {@link Intent#ACTION_PACKAGE_ADDED}. * This method returns immediately, and will continue to work in an @@ -103,15 +103,18 @@ public class InstalledAppProviderService extends IntentService { * {@link Process#THREAD_PRIORITY_LOWEST}. */ public static void compareToPackageManager(Context context) { - Map cachedInfo = InstalledAppProvider.Helper.all(context); + Map cachedInfo = InstalledAppProvider.Helper.all(context); List packageInfoList = context.getPackageManager() .getInstalledPackages(PackageManager.GET_SIGNATURES); - // TODO check packageInfo.lastUpdateTime for freshness for (PackageInfo packageInfo : packageInfoList) { - insert(context, packageInfo); if (cachedInfo.containsKey(packageInfo.packageName)) { + if (packageInfo.lastUpdateTime > cachedInfo.get(packageInfo.packageName)) { + insert(context, packageInfo); + } cachedInfo.remove(packageInfo.packageName); + } else { + insert(context, packageInfo); } }