From 395efa2e3fa5f0e83f2dfc9a2636e9d8cf30aba1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 27 Jul 2018 16:51:35 +0200 Subject: [PATCH] mark app as installed only after F-Droid has processed the installed APK InstalledAppProviderService also updates the AppUpdateStatus of any package installs that are still in progress. Most importantly, this provides the final status update to mark the end of the installation process. It also errors out installation processes where some outside factor uninstalled the package while the F-Droid process was underway, e.g. uninstalling via adb, updates via Google Play, Yalp, etc. fdroid/fdroidclient#1536 fdroid/fdroidclient#1357 --- .../data/InstalledAppProviderService.java | 18 +++++++++++++++++- .../installer/InstallManagerService.java | 18 ------------------ 2 files changed, 17 insertions(+), 19 deletions(-) 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 5f01aa7bd..2afc56f75 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -12,6 +12,7 @@ import android.support.annotation.Nullable; import android.support.v4.app.JobIntentService; import android.util.Log; import org.acra.ACRA; +import org.fdroid.fdroid.AppUpdateStatusManager; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Schema.InstalledAppTable; import rx.functions.Action1; @@ -31,13 +32,21 @@ 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, * {@link #insertAppIntoDb(Context, PackageInfo, String, String)} and * {@link #deleteAppFromDb(Context, String)} are both static methods to enable easy testing * of this stuff. + *

+ * This also updates the {@link AppUpdateStatusManager.Status status} of any + * package installs that are still in progress. Most importantly, this + * provides the final {@link AppUpdateStatusManager.Status#Installed status update} + * to mark the end of the installation process. It also errors out installation + * processes where some outside factor uninstalled the package while the F-Droid + * process was underway, e.g. uninstalling via {@code adb}, updates via Google + * Play, Yalp, etc. */ @SuppressWarnings("LineLength") public class InstalledAppProviderService extends JobIntentService { @@ -221,11 +230,15 @@ public class InstalledAppProviderService extends JobIntentService { protected void onHandleWork(@NonNull Intent intent) { Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST); + AppUpdateStatusManager ausm = AppUpdateStatusManager.getInstance(this); String packageName = intent.getData().getSchemeSpecificPart(); final String action = intent.getAction(); if (ACTION_INSERT.equals(action)) { PackageInfo packageInfo = getPackageInfo(intent, packageName); if (packageInfo != null) { + for (AppUpdateStatusManager.AppUpdateStatus status : ausm.getByPackageName(packageName)) { + ausm.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.Installed, null); + } File apk = getPathToInstalledApk(packageInfo); if (apk == null) { return; @@ -244,6 +257,9 @@ public class InstalledAppProviderService extends JobIntentService { } } else if (ACTION_DELETE.equals(action)) { deleteAppFromDb(this, packageName); + for (AppUpdateStatusManager.AppUpdateStatus status : ausm.getByPackageName(packageName)) { + ausm.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.InstallError, null); + } } packageChangeNotifier.onNext(packageName); } diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java index 50d63e3e4..726b1496f 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -6,7 +6,6 @@ import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.net.Uri; @@ -95,7 +94,6 @@ public class InstallManagerService extends Service { private LocalBroadcastManager localBroadcastManager; private AppUpdateStatusManager appUpdateStatusManager; - private BroadcastReceiver broadcastReceiver; private boolean running = false; /** @@ -111,21 +109,6 @@ public class InstallManagerService extends Service { super.onCreate(); localBroadcastManager = LocalBroadcastManager.getInstance(this); appUpdateStatusManager = AppUpdateStatusManager.getInstance(this); - - broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getData() == null) return; - String packageName = intent.getData().getSchemeSpecificPart(); - for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(packageName)) { - appUpdateStatusManager.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.Installed, null); - } - } - }; - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); - intentFilter.addDataScheme("package"); - registerReceiver(broadcastReceiver, intentFilter); running = true; pendingInstalls = getPendingInstalls(this); } @@ -140,7 +123,6 @@ public class InstallManagerService extends Service { @Override public void onDestroy() { running = false; - unregisterReceiver(broadcastReceiver); super.onDestroy(); }