From a0b318c3834161d4746a263940c343ca32c45a22 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 26 Mar 2019 12:07:46 +0100 Subject: [PATCH 01/14] rename Apk.getUrl() to getCanonicalUrl() to highlight it is also an ID This method returns the URL that points to the canonical download source for this package. This is also used as the unique ID for tracking downloading, progress, and notifications throughout the whole install process. It is guaranteed to uniquely represent this file since it points to a file on the file system of the canonical webserver. --- .../org/fdroid/fdroid/views/swap/SwapAppsView.java | 2 +- .../fdroid/views/swap/SwapWorkflowActivity.java | 2 +- .../org/fdroid/fdroid/AppUpdateStatusManager.java | 8 ++++---- app/src/main/java/org/fdroid/fdroid/data/Apk.java | 13 +++++++++++-- .../fdroid/installer/InstallManagerService.java | 4 ++-- .../fdroid/views/apps/AppListItemController.java | 4 ++-- .../items/KnownVulnAppListItemController.java | 2 +- 7 files changed, 22 insertions(+), 13 deletions(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java index 839cf8c5b..7ad2f38eb 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java +++ b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java @@ -314,7 +314,7 @@ public class SwapAppsView extends ListView implements } if (apk != null) { - String urlString = apk.getUrl(); + String urlString = apk.getCanonicalUrl(); // TODO unregister receivers? or will they just die with this instance IntentFilter downloadFilter = DownloaderService.getIntentFilter(urlString); diff --git a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java index e3b1cb276..a8a426db9 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -836,7 +836,7 @@ public class SwapWorkflowActivity extends AppCompatActivity { } public void install(@NonNull final App app, @NonNull final Apk apk) { - Uri downloadUri = Uri.parse(apk.getUrl()); + Uri downloadUri = Uri.parse(apk.getCanonicalUrl()); localBroadcastManager.registerReceiver(installReceiver, Installer.getInstallIntentFilter(downloadUri)); InstallManagerService.queue(this, app, apk); diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java index 020a817dd..14c7bda14 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java +++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java @@ -133,7 +133,7 @@ public final class AppUpdateStatusManager { * @see org.fdroid.fdroid.installer.InstallManagerService */ public String getUniqueKey() { - return apk.getUrl(); + return apk.getCanonicalUrl(); } /** @@ -321,7 +321,7 @@ public final class AppUpdateStatusManager { ContentResolver resolver = context.getContentResolver(); App app = AppProvider.Helper.findSpecificApp(resolver, apk.packageName, apk.repoId); AppUpdateStatus ret = new AppUpdateStatus(app, apk, status, intent); - appMapping.put(apk.getUrl(), ret); + appMapping.put(apk.getCanonicalUrl(), ret); return ret; } } @@ -347,7 +347,7 @@ public final class AppUpdateStatusManager { } synchronized (appMapping) { - AppUpdateStatus entry = appMapping.get(apk.getUrl()); + AppUpdateStatus entry = appMapping.get(apk.getCanonicalUrl()); if (entry != null) { updateApkInternal(entry, status, pendingIntent); } else { @@ -435,7 +435,7 @@ public final class AppUpdateStatusManager { public void setApkError(Apk apk, String errorText) { synchronized (appMapping) { - AppUpdateStatus entry = appMapping.get(apk.getUrl()); + AppUpdateStatus entry = appMapping.get(apk.getCanonicalUrl()); if (entry == null) { entry = createAppEntry(apk, Status.InstallError, null); } diff --git a/app/src/main/java/org/fdroid/fdroid/data/Apk.java b/app/src/main/java/org/fdroid/fdroid/data/Apk.java index 0cdae110c..b70506203 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Apk.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Apk.java @@ -263,8 +263,17 @@ public class Apk extends ValueObject implements Comparable, Parcelable { } } + /** + * Get the URL that points to the canonical download source for this + * package. This is also used as the unique ID for tracking downloading, + * progress, and notifications throughout the whole install process. It + * is guaranteed to uniquely represent this file since it points to a file + * on the file system of the canonical webserver. + * + * @see org.fdroid.fdroid.installer.InstallManagerService + */ @JsonIgnore // prevent tests from failing due to nulls in checkRepoAddress() - public String getUrl() { + public String getCanonicalUrl() { checkRepoAddress(); return repoAddress + "/" + apkName.replace(" ", "%20"); } @@ -527,7 +536,7 @@ public class Apk extends ValueObject implements Comparable, Parcelable { public File getMediaInstallPath(Context context) { File path = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DOWNLOADS); // Default for all other non-apk/media files - String fileExtension = MimeTypeMap.getFileExtensionFromUrl(this.getUrl()); + String fileExtension = MimeTypeMap.getFileExtensionFromUrl(this.getCanonicalUrl()); if (TextUtils.isEmpty(fileExtension)) return path; MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); String[] mimeType = mimeTypeMap.getMimeTypeFromExtension(fileExtension).split("/"); 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 3ba2a632a..74cd5eda0 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -209,7 +209,7 @@ public class InstallManagerService extends Service { getObb(urlString, apk.getMainObbUrl(), apk.getMainObbFile(), apk.obbMainFileSha256); getObb(urlString, apk.getPatchObbUrl(), apk.getPatchObbFile(), apk.obbPatchFileSha256); - File apkFilePath = ApkCache.getApkDownloadPath(this, apk.getUrl()); + File apkFilePath = ApkCache.getApkDownloadPath(this, apk.getCanonicalUrl()); long apkFileSize = apkFilePath.length(); if (!apkFilePath.exists() || apkFileSize < apk.size) { Utils.debugLog(TAG, "download " + urlString + " " + apkFilePath); @@ -464,7 +464,7 @@ public class InstallManagerService extends Service { * @param context this app's {@link Context} */ public static void queue(Context context, App app, @NonNull Apk apk) { - String urlString = apk.getUrl(); + String urlString = apk.getCanonicalUrl(); AppUpdateStatusManager.getInstance(context).addApk(apk, AppUpdateStatusManager.Status.PendingInstall, null); putPendingInstall(context, urlString, apk.packageName); Utils.debugLog(TAG, "queue " + app.packageName + " " + apk.versionCode + " from " + urlString); diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index 9427c5f45..520311045 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -483,9 +483,9 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { } if (currentStatus != null && currentStatus.status == AppUpdateStatusManager.Status.ReadyToInstall) { - String urlString = currentStatus.apk.getUrl(); + String urlString = currentStatus.apk.getCanonicalUrl(); File apkFilePath = ApkCache.getApkDownloadPath(activity, urlString); - Utils.debugLog(TAG, "skip download, we have already downloaded " + currentStatus.apk.getUrl() + + Utils.debugLog(TAG, "skip download, we have already downloaded " + currentStatus.apk.getCanonicalUrl() + " to " + apkFilePath); final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(activity); diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java index 6d3631940..a4d89fa7f 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java @@ -73,7 +73,7 @@ public class KnownVulnAppListItemController extends AppListItemController { Apk suggestedApk = ApkProvider.Helper.findSuggestedApk(activity, app); if (shouldUpgradeInsteadOfUninstall(app, suggestedApk)) { LocalBroadcastManager manager = LocalBroadcastManager.getInstance(activity); - Uri uri = Uri.parse(suggestedApk.getUrl()); + Uri uri = Uri.parse(suggestedApk.getCanonicalUrl()); manager.registerReceiver(installReceiver, Installer.getInstallIntentFilter(uri)); InstallManagerService.queue(activity, app, suggestedApk); } else { From 4ea775be002ebe3b6a555c25c63f1cf38b62f19f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 26 Mar 2019 12:14:59 +0100 Subject: [PATCH 02/14] remove wrong "ERROR" description from Downloader Intend Extras Looks like a copy-paste bug in a160476a14c40412728f4974f53d1a18f7064346 --- app/src/main/java/org/fdroid/fdroid/net/Downloader.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java index 7a7ebb232..04b215543 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java +++ b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java @@ -29,9 +29,9 @@ public abstract class Downloader { public static final String EXTRA_BYTES_READ = "org.fdroid.fdroid.net.Downloader.extra.BYTES_READ"; public static final String EXTRA_TOTAL_BYTES = "org.fdroid.fdroid.net.Downloader.extra.TOTAL_BYTES"; public static final String EXTRA_ERROR_MESSAGE = "org.fdroid.fdroid.net.Downloader.extra.ERROR_MESSAGE"; - public static final String EXTRA_REPO_ID = "org.fdroid.fdroid.net.Downloader.extra.ERROR_REPO_ID"; - public static final String EXTRA_CANONICAL_URL = "org.fdroid.fdroid.net.Downloader.extra.ERROR_CANONICAL_URL"; - public static final String EXTRA_MIRROR_URL = "org.fdroid.fdroid.net.Downloader.extra.ERROR_MIRROR_URL"; + public static final String EXTRA_REPO_ID = "org.fdroid.fdroid.net.Downloader.extra.REPO_ID"; + public static final String EXTRA_CANONICAL_URL = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL"; + public static final String EXTRA_MIRROR_URL = "org.fdroid.fdroid.net.Downloader.extra.MIRROR_URL"; public static final int DEFAULT_TIMEOUT = 10000; public static final int SECOND_TIMEOUT = (int) DateUtils.MINUTE_IN_MILLIS; From e346d2351b86afa42cb4712251807a4350a61bf7 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 26 Mar 2019 13:35:19 +0100 Subject: [PATCH 03/14] rename AppUpdateStatus.getUniqueKey to getCanonicalUrl This highlights the relationship between the various things that are using the canonical URL as the unique ID. --- .../fdroid/fdroid/AppUpdateStatusManager.java | 17 ++++++------ .../org/fdroid/fdroid/NotificationHelper.java | 26 +++++++++---------- .../data/InstalledAppProviderService.java | 4 +-- .../fdroid/views/AppDetailsActivity.java | 16 ++++++------ .../views/apps/AppListItemController.java | 4 +-- .../items/AppStatusListItemController.java | 2 +- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java index 14c7bda14..1192cc778 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java +++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java @@ -132,7 +132,7 @@ public final class AppUpdateStatusManager { * also known as {@code urlString}. * @see org.fdroid.fdroid.installer.InstallManagerService */ - public String getUniqueKey() { + public String getCanonicalUrl() { return apk.getCanonicalUrl(); } @@ -264,7 +264,7 @@ public final class AppUpdateStatusManager { notifyChange(entry, isStatusUpdate); if (status == Status.Installed) { - InstallManagerService.removePendingInstall(context, entry.getUniqueKey()); + InstallManagerService.removePendingInstall(context, entry.getCanonicalUrl()); } } @@ -272,11 +272,11 @@ public final class AppUpdateStatusManager { Utils.debugLog(LOGTAG, "Add APK " + apk.apkName + " with state " + status.name()); AppUpdateStatus entry = createAppEntry(apk, status, intent); setEntryContentIntentIfEmpty(entry); - appMapping.put(entry.getUniqueKey(), entry); + appMapping.put(entry.getCanonicalUrl(), entry); notifyAdd(entry); if (status == Status.Installed) { - InstallManagerService.removePendingInstall(context, entry.getUniqueKey()); + InstallManagerService.removePendingInstall(context, entry.getCanonicalUrl()); } } @@ -291,7 +291,7 @@ public final class AppUpdateStatusManager { private void notifyAdd(AppUpdateStatus entry) { if (!isBatchUpdating) { Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_ADDED); - broadcastIntent.putExtra(EXTRA_APK_URL, entry.getUniqueKey()); + broadcastIntent.putExtra(EXTRA_APK_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); localBroadcastManager.sendBroadcast(broadcastIntent); } @@ -300,7 +300,7 @@ public final class AppUpdateStatusManager { private void notifyChange(AppUpdateStatus entry, boolean isStatusUpdate) { if (!isBatchUpdating) { Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_CHANGED); - broadcastIntent.putExtra(EXTRA_APK_URL, entry.getUniqueKey()); + broadcastIntent.putExtra(EXTRA_APK_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); broadcastIntent.putExtra(EXTRA_IS_STATUS_UPDATE, isStatusUpdate); localBroadcastManager.sendBroadcast(broadcastIntent); @@ -310,7 +310,7 @@ public final class AppUpdateStatusManager { private void notifyRemove(AppUpdateStatus entry) { if (!isBatchUpdating) { Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_REMOVED); - broadcastIntent.putExtra(EXTRA_APK_URL, entry.getUniqueKey()); + broadcastIntent.putExtra(EXTRA_APK_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); localBroadcastManager.sendBroadcast(broadcastIntent); } @@ -420,6 +420,7 @@ public final class AppUpdateStatusManager { /** * @param errorText If null, then it is likely because the user cancelled the download. */ + // TODO should url actually be canonicalUrl? public void setDownloadError(String url, @Nullable String errorText) { synchronized (appMapping) { AppUpdateStatus entry = appMapping.get(url); @@ -444,7 +445,7 @@ public final class AppUpdateStatusManager { entry.intent = getAppErrorIntent(entry); notifyChange(entry, false); - InstallManagerService.removePendingInstall(context, entry.getUniqueKey()); + InstallManagerService.removePendingInstall(context, entry.getCanonicalUrl()); } } diff --git a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java index a7639ecc9..4841b9c7f 100644 --- a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java @@ -164,8 +164,8 @@ class NotificationHelper { private void createNotification(AppUpdateStatusManager.AppUpdateStatus entry) { if (shouldIgnoreEntry(entry)) { - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES); - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED); return; } @@ -177,23 +177,23 @@ class NotificationHelper { if (entry.status == AppUpdateStatusManager.Status.Installed) { if (useStackedNotifications()) { notification = createInstalledNotification(entry); - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES); - notificationManager.notify(entry.getUniqueKey(), NOTIFY_ID_INSTALLED, notification); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES); + notificationManager.notify(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED, notification); } else if (installed.size() == 1) { notification = createInstalledNotification(entry); - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES); - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED); notificationManager.notify(GROUP_INSTALLED, NOTIFY_ID_INSTALLED, notification); } } else { if (useStackedNotifications()) { notification = createUpdateNotification(entry); - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED); - notificationManager.notify(entry.getUniqueKey(), NOTIFY_ID_UPDATES, notification); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED); + notificationManager.notify(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES, notification); } else if (updates.size() == 1) { notification = createUpdateNotification(entry); - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_UPDATES); - notificationManager.cancel(entry.getUniqueKey(), NOTIFY_ID_INSTALLED); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_UPDATES); + notificationManager.cancel(entry.getCanonicalUrl(), NOTIFY_ID_INSTALLED); notificationManager.notify(GROUP_UPDATES, NOTIFY_ID_UPDATES, notification); } } @@ -346,7 +346,7 @@ class NotificationHelper { } Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED); - intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getUniqueKey()); + intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getCanonicalUrl()); intentDeleted.setClass(context, NotificationBroadcastReceiver.class); PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT); builder.setDeleteIntent(piDeleted); @@ -435,7 +435,7 @@ class NotificationHelper { } Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED); - intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getUniqueKey()); + intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getCanonicalUrl()); intentDeleted.setClass(context, NotificationBroadcastReceiver.class); PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT); builder.setDeleteIntent(piDeleted); @@ -540,7 +540,7 @@ class NotificationHelper { public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { // Need to check that the notification is still valid, and also that the image // is indeed cached now, so we won't get stuck in an endless loop. - AppUpdateStatusManager.AppUpdateStatus oldEntry = appUpdateStatusManager.get(entry.getUniqueKey()); + AppUpdateStatusManager.AppUpdateStatus oldEntry = appUpdateStatusManager.get(entry.getCanonicalUrl()); if (oldEntry != null && oldEntry.app != null && oldEntry.app.iconUrl != null 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 9915bf9e1..e827edca7 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -237,7 +237,7 @@ public class InstalledAppProviderService extends JobIntentService { PackageInfo packageInfo = getPackageInfo(intent, packageName); if (packageInfo != null) { for (AppUpdateStatusManager.AppUpdateStatus status : ausm.getByPackageName(packageName)) { - ausm.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.Installed, null); + ausm.updateApk(status.getCanonicalUrl(), AppUpdateStatusManager.Status.Installed, null); } File apk = getPathToInstalledApk(packageInfo); if (apk == null) { @@ -258,7 +258,7 @@ 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); + ausm.updateApk(status.getCanonicalUrl(), AppUpdateStatusManager.Status.InstallError, null); } } packageChangeNotifier.onNext(packageName); diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java index 1d606c4fd..ec554956a 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java @@ -171,9 +171,9 @@ public class AppDetailsActivity extends AppCompatActivity AppUpdateStatusManager ausm = AppUpdateStatusManager.getInstance(this); for (AppUpdateStatusManager.AppUpdateStatus status : ausm.getByPackageName(app.packageName)) { if (status.status == AppUpdateStatusManager.Status.Installed) { - ausm.removeApk(status.getUniqueKey()); + ausm.removeApk(status.getCanonicalUrl()); } else { - ausm.refreshApk(status.getUniqueKey()); + ausm.refreshApk(status.getCanonicalUrl()); } } } @@ -449,7 +449,7 @@ public class AppDetailsActivity extends AppCompatActivity if (justReceived) { adapter.setIndeterminateProgress(R.string.installing); localBroadcastManager.registerReceiver(installReceiver, - Installer.getInstallIntentFilter(Uri.parse(newStatus.getUniqueKey()))); + Installer.getInstallIntentFilter(Uri.parse(newStatus.getCanonicalUrl()))); } break; @@ -459,7 +459,7 @@ public class AppDetailsActivity extends AppCompatActivity Toast.makeText(this, R.string.details_notinstalled, Toast.LENGTH_LONG).show(); } else { String msg = newStatus.errorText; - if (!newStatus.getUniqueKey().equals(msg)) msg += " " + newStatus.getUniqueKey(); + if (!newStatus.getCanonicalUrl().equals(msg)) msg += " " + newStatus.getCanonicalUrl(); Toast.makeText(this, R.string.download_error, Toast.LENGTH_SHORT).show(); Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); } @@ -491,9 +491,9 @@ public class AppDetailsActivity extends AppCompatActivity AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED); if (currentStatus != null && isRemoving - && !TextUtils.equals(status.getUniqueKey(), currentStatus.getUniqueKey())) { + && !TextUtils.equals(status.getCanonicalUrl(), currentStatus.getCanonicalUrl())) { Utils.debugLog(TAG, "Ignoring app status change because it belongs to " - + status.getUniqueKey() + " not " + currentStatus.getUniqueKey()); + + status.getCanonicalUrl() + " not " + currentStatus.getCanonicalUrl()); } else if (status != null && !TextUtils.equals(status.apk.packageName, app.packageName)) { Utils.debugLog(TAG, "Ignoring app status change because it belongs to " + status.apk.packageName + " not " + app.packageName); @@ -650,7 +650,7 @@ public class AppDetailsActivity extends AppCompatActivity AppUpdateStatusManager ausm = AppUpdateStatusManager.getInstance(this); for (AppUpdateStatusManager.AppUpdateStatus status : ausm.getByPackageName(packageName)) { if (status.status == AppUpdateStatusManager.Status.Installed) { - ausm.removeApk(status.getUniqueKey()); + ausm.removeApk(status.getCanonicalUrl()); } } if (app == null) { @@ -720,7 +720,7 @@ public class AppDetailsActivity extends AppCompatActivity @Override public void installCancel() { if (currentStatus != null) { - InstallManagerService.cancel(this, currentStatus.getUniqueKey()); + InstallManagerService.cancel(this, currentStatus.getCanonicalUrl()); } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index 520311045..fde7af64e 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -477,7 +477,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { // Once it is explicitly launched by the user, then we can pretty much forget about // any sort of notification that the app was successfully installed. It should be // apparent to the user because they just launched it. - AppUpdateStatusManager.getInstance(activity).removeApk(currentStatus.getUniqueKey()); + AppUpdateStatusManager.getInstance(activity).removeApk(currentStatus.getCanonicalUrl()); } return; } @@ -534,6 +534,6 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { return; } - InstallManagerService.cancel(activity, currentStatus.getUniqueKey()); + InstallManagerService.cancel(activity, currentStatus.getCanonicalUrl()); } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java index 4bf93f9e0..2f612ca16 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java @@ -59,7 +59,7 @@ public class AppStatusListItemController extends AppListItemController { CharSequence message = null; if (status != null) { AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(activity); - manager.removeApk(status.getUniqueKey()); + manager.removeApk(status.getCanonicalUrl()); switch (status.status) { case Downloading: cancelDownload(); From 6b0a784a2676dcfb1388831766c7e18ec7f2b757 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 26 Mar 2019 13:48:45 +0100 Subject: [PATCH 04/14] normalize canonical URL variable names --- .../fdroid/fdroid/AppUpdateStatusManager.java | 24 +++++++------- .../installer/InstallManagerService.java | 28 ++++++++-------- .../fdroid/fdroid/net/DownloaderService.java | 32 +++++++++---------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java index 1192cc778..a1372c619 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java +++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java @@ -359,9 +359,9 @@ public final class AppUpdateStatusManager { /** * @param pendingIntent Action when notification is clicked. Can be null for default action(s) */ - public void updateApk(String key, @NonNull Status status, @Nullable PendingIntent pendingIntent) { + public void updateApk(String canonicalUrl, @NonNull Status status, @Nullable PendingIntent pendingIntent) { synchronized (appMapping) { - AppUpdateStatus entry = appMapping.get(key); + AppUpdateStatus entry = appMapping.get(canonicalUrl); if (entry != null) { updateApkInternal(entry, status, pendingIntent); } @@ -369,9 +369,9 @@ public final class AppUpdateStatusManager { } @Nullable - public Apk getApk(String key) { + public Apk getApk(String canonicalUrl) { synchronized (appMapping) { - AppUpdateStatus entry = appMapping.get(key); + AppUpdateStatus entry = appMapping.get(canonicalUrl); if (entry != null) { return entry.apk; } @@ -382,13 +382,13 @@ public final class AppUpdateStatusManager { /** * Remove an APK from being tracked, since it is now considered {@link Status#Installed} * - * @param key the unique ID for the install process, also called {@code urlString} + * @param canonicalUrl the unique ID for the install process * @see org.fdroid.fdroid.installer.InstallManagerService */ - public void removeApk(String key) { + public void removeApk(String canonicalUrl) { synchronized (appMapping) { - InstallManagerService.removePendingInstall(context, key); - AppUpdateStatus entry = appMapping.remove(key); + InstallManagerService.removePendingInstall(context, canonicalUrl); + AppUpdateStatus entry = appMapping.remove(canonicalUrl); if (entry != null) { Utils.debugLog(LOGTAG, "Remove APK " + entry.apk.apkName); notifyRemove(entry); @@ -396,9 +396,9 @@ public final class AppUpdateStatusManager { } } - public void refreshApk(String key) { + public void refreshApk(String canonicalUrl) { synchronized (appMapping) { - AppUpdateStatus entry = appMapping.get(key); + AppUpdateStatus entry = appMapping.get(canonicalUrl); if (entry != null) { Utils.debugLog(LOGTAG, "Refresh APK " + entry.apk.apkName); notifyChange(entry, true); @@ -406,9 +406,9 @@ public final class AppUpdateStatusManager { } } - public void updateApkProgress(String key, long max, long current) { + public void updateApkProgress(String canonicalUrl, long max, long current) { synchronized (appMapping) { - AppUpdateStatus entry = appMapping.get(key); + AppUpdateStatus entry = appMapping.get(canonicalUrl); if (entry != null) { entry.progressMax = max; entry.progressCurrent = current; 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 74cd5eda0..2329d045b 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -464,23 +464,23 @@ public class InstallManagerService extends Service { * @param context this app's {@link Context} */ public static void queue(Context context, App app, @NonNull Apk apk) { - String urlString = apk.getCanonicalUrl(); + String canonicalUrl = apk.getCanonicalUrl(); AppUpdateStatusManager.getInstance(context).addApk(apk, AppUpdateStatusManager.Status.PendingInstall, null); - putPendingInstall(context, urlString, apk.packageName); - Utils.debugLog(TAG, "queue " + app.packageName + " " + apk.versionCode + " from " + urlString); + putPendingInstall(context, canonicalUrl, apk.packageName); + Utils.debugLog(TAG, "queue " + app.packageName + " " + apk.versionCode + " from " + canonicalUrl); Intent intent = new Intent(context, InstallManagerService.class); intent.setAction(ACTION_INSTALL); - intent.setData(Uri.parse(urlString)); + intent.setData(Uri.parse(canonicalUrl)); intent.putExtra(EXTRA_APP, app); intent.putExtra(EXTRA_APK, apk); context.startService(intent); } - public static void cancel(Context context, String urlString) { - removePendingInstall(context, urlString); + public static void cancel(Context context, String canonicalUrl) { + removePendingInstall(context, canonicalUrl); Intent intent = new Intent(context, InstallManagerService.class); intent.setAction(ACTION_CANCEL); - intent.setData(Uri.parse(urlString)); + intent.setData(Uri.parse(canonicalUrl)); context.startService(intent); } @@ -491,29 +491,29 @@ public class InstallManagerService extends Service { * completed, or the device lost power in the middle of the install * process. */ - public boolean isPendingInstall(String urlString) { - return pendingInstalls.contains(urlString); + public boolean isPendingInstall(String canonicalUrl) { + return pendingInstalls.contains(canonicalUrl); } /** * Mark a given APK as in the process of being installed, with - * the {@code urlString} of the download used as the unique ID, + * the {@code canonicalUrl} of the download used as the unique ID, * and the file hash used to verify that things are the same. * * @see #isPendingInstall(String) */ - public static void putPendingInstall(Context context, String urlString, String packageName) { + public static void putPendingInstall(Context context, String canonicalUrl, String packageName) { if (pendingInstalls == null) { pendingInstalls = getPendingInstalls(context); } - pendingInstalls.edit().putString(urlString, packageName).apply(); + pendingInstalls.edit().putString(canonicalUrl, packageName).apply(); } - public static void removePendingInstall(Context context, String urlString) { + public static void removePendingInstall(Context context, String canonicalUrl) { if (pendingInstalls == null) { pendingInstalls = getPendingInstalls(context); } - pendingInstalls.edit().remove(urlString).apply(); + pendingInstalls.edit().remove(canonicalUrl).apply(); } private static SharedPreferences getPendingInstalls(Context context) { diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index 30b8e4410..efbd57a45 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -199,9 +199,9 @@ public class DownloaderService extends Service { private void handleIntent(Intent intent) { final Uri uri = intent.getData(); long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); - String canonicalUrlString = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); - final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, canonicalUrlString); - sendBroadcast(uri, Downloader.ACTION_STARTED, localFile, repoId, canonicalUrlString); + String canonicalUrl = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); + final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, canonicalUrl); + sendBroadcast(uri, Downloader.ACTION_STARTED, localFile, repoId, canonicalUrl); try { downloader = DownloaderFactory.create(this, uri, localFile); @@ -219,22 +219,22 @@ public class DownloaderService extends Service { downloader.download(); if (downloader.isNotFound()) { sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, getString(R.string.download_404), - repoId, canonicalUrlString); + repoId, canonicalUrl); } else { - sendBroadcast(uri, Downloader.ACTION_COMPLETE, localFile, repoId, canonicalUrlString); + sendBroadcast(uri, Downloader.ACTION_COMPLETE, localFile, repoId, canonicalUrl); } } catch (InterruptedException e) { - sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, repoId, canonicalUrlString); + sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, repoId, canonicalUrl); } catch (ConnectException | HttpRetryException | NoRouteToHostException | SocketTimeoutException | SSLHandshakeException | SSLKeyException | SSLPeerUnverifiedException | SSLProtocolException | ProtocolException | UnknownHostException e) { // if the above list of exceptions changes, also change it in IndexV1Updater.update() Log.e(TAG, e.getLocalizedMessage()); - sendBroadcast(uri, Downloader.ACTION_CONNECTION_FAILED, localFile, repoId, canonicalUrlString); + sendBroadcast(uri, Downloader.ACTION_CONNECTION_FAILED, localFile, repoId, canonicalUrl); } catch (IOException e) { e.printStackTrace(); sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, - e.getLocalizedMessage(), repoId, canonicalUrlString); + e.getLocalizedMessage(), repoId, canonicalUrl); } finally { if (downloader != null) { downloader.close(); @@ -247,8 +247,8 @@ public class DownloaderService extends Service { sendBroadcast(uri, action, null, null); } - private void sendBroadcast(Uri uri, String action, File file, long repoId, String originalUrlString) { - sendBroadcast(uri, action, file, null, repoId, originalUrlString); + private void sendBroadcast(Uri uri, String action, File file, long repoId, String canonicalUrl) { + sendBroadcast(uri, action, file, null, repoId, canonicalUrl); } private void sendBroadcast(Uri uri, String action, File file, String errorMessage) { @@ -256,10 +256,10 @@ public class DownloaderService extends Service { } private void sendBroadcast(Uri uri, String action, File file, String errorMessage, long repoId, - String originalUrlString) { + String canonicalUrl) { Intent intent = new Intent(action); - if (originalUrlString != null) { - intent.setData(Uri.parse(originalUrlString)); + if (canonicalUrl != null) { + intent.setData(Uri.parse(canonicalUrl)); } if (file != null) { intent.putExtra(Downloader.EXTRA_DOWNLOAD_PATH, file.getAbsolutePath()); @@ -280,10 +280,10 @@ public class DownloaderService extends Service { * @param context this app's {@link Context} * @param mirrorUrlString The URL to add to the download queue * @param repoId the database ID number representing one repo - * @param urlString the URL used as the unique ID throughout F-Droid + * @param canonicalUrl the URL used as the unique ID throughout F-Droid * @see #cancel(Context, String) */ - public static void queue(Context context, String mirrorUrlString, long repoId, String urlString) { + public static void queue(Context context, String mirrorUrlString, long repoId, String canonicalUrl) { if (TextUtils.isEmpty(mirrorUrlString)) { return; } @@ -292,7 +292,7 @@ public class DownloaderService extends Service { intent.setAction(ACTION_QUEUE); intent.setData(Uri.parse(mirrorUrlString)); intent.putExtra(Downloader.EXTRA_REPO_ID, repoId); - intent.putExtra(Downloader.EXTRA_CANONICAL_URL, urlString); + intent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUrl); context.startService(intent); } From d794c5a77c5c607c9562d4c3e0e941d6a7913450 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 11:41:03 +0100 Subject: [PATCH 05/14] purge urlString from ProgressListener, it is unused and confusing --- .../java/org/fdroid/fdroid/net/HttpDownloaderTest.java | 4 ++-- app/src/main/java/org/fdroid/fdroid/IndexUpdater.java | 6 +++--- app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java | 2 +- .../java/org/fdroid/fdroid/ProgressBufferedInputStream.java | 6 ++---- app/src/main/java/org/fdroid/fdroid/ProgressListener.java | 2 +- app/src/main/java/org/fdroid/fdroid/net/Downloader.java | 2 +- .../main/java/org/fdroid/fdroid/net/DownloaderService.java | 2 +- 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java b/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java index 57238613d..4356f4564 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java +++ b/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java @@ -70,7 +70,7 @@ public class HttpDownloaderTest { final HttpDownloader httpDownloader = new HttpDownloader(uri, destFile); httpDownloader.setListener(new ProgressListener() { @Override - public void onProgress(String urlString, long bytesRead, long totalBytes) { + public void onProgress(long bytesRead, long totalBytes) { receivedProgress = true; } }); @@ -132,7 +132,7 @@ public class HttpDownloaderTest { final HttpDownloader httpDownloader = new HttpDownloader(uri, destFile); httpDownloader.setListener(new ProgressListener() { @Override - public void onProgress(String urlString, long bytesRead, long totalBytes) { + public void onProgress(long bytesRead, long totalBytes) { receivedProgress = true; latch.countDown(); } diff --git a/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java b/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java index d4ad76cc1..3a267144a 100644 --- a/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java +++ b/app/src/main/java/org/fdroid/fdroid/IndexUpdater.java @@ -216,7 +216,7 @@ public class IndexUpdater { JarFile jarFile = new JarFile(downloadedFile, true); JarEntry indexEntry = (JarEntry) jarFile.getEntry(IndexUpdater.DATA_FILE_NAME); indexInputStream = new ProgressBufferedInputStream(jarFile.getInputStream(indexEntry), - processIndexListener, repo.address, (int) indexEntry.getSize()); + processIndexListener, (int) indexEntry.getSize()); // Process the index... SAXParserFactory factory = SAXParserFactory.newInstance(); @@ -254,14 +254,14 @@ public class IndexUpdater { protected final ProgressListener downloadListener = new ProgressListener() { @Override - public void onProgress(String urlString, long bytesRead, long totalBytes) { + public void onProgress(long bytesRead, long totalBytes) { UpdateService.reportDownloadProgress(context, IndexUpdater.this, bytesRead, totalBytes); } }; protected final ProgressListener processIndexListener = new ProgressListener() { @Override - public void onProgress(String urlString, long bytesRead, long totalBytes) { + public void onProgress(long bytesRead, long totalBytes) { UpdateService.reportProcessIndexProgress(context, IndexUpdater.this, bytesRead, totalBytes); } }; diff --git a/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java b/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java index 518b23016..44405fb43 100644 --- a/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java +++ b/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java @@ -198,7 +198,7 @@ public class IndexV1Updater extends IndexUpdater { JarFile jarFile = new JarFile(outputFile, true); JarEntry indexEntry = (JarEntry) jarFile.getEntry(DATA_FILE_NAME); InputStream indexInputStream = new ProgressBufferedInputStream(jarFile.getInputStream(indexEntry), - processIndexListener, repo.address, (int) indexEntry.getSize()); + processIndexListener, (int) indexEntry.getSize()); processIndexV1(indexInputStream, indexEntry, cacheTag); } diff --git a/app/src/main/java/org/fdroid/fdroid/ProgressBufferedInputStream.java b/app/src/main/java/org/fdroid/fdroid/ProgressBufferedInputStream.java index 1340877fd..25aad6dc9 100644 --- a/app/src/main/java/org/fdroid/fdroid/ProgressBufferedInputStream.java +++ b/app/src/main/java/org/fdroid/fdroid/ProgressBufferedInputStream.java @@ -9,7 +9,6 @@ import java.io.InputStream; class ProgressBufferedInputStream extends BufferedInputStream { private final ProgressListener progressListener; - private final String urlString; private final int totalBytes; private int currentBytes; @@ -18,10 +17,9 @@ class ProgressBufferedInputStream extends BufferedInputStream { * Reports progress to the specified {@link ProgressListener}, with the * progress based on the {@code totalBytes}. */ - ProgressBufferedInputStream(InputStream in, ProgressListener progressListener, String urlString, int totalBytes) { + ProgressBufferedInputStream(InputStream in, ProgressListener progressListener, int totalBytes) { super(in); this.progressListener = progressListener; - this.urlString = urlString; this.totalBytes = totalBytes; } @@ -33,7 +31,7 @@ class ProgressBufferedInputStream extends BufferedInputStream { * the digits changing because it looks pretty, < 9000 since the reads won't * line up exactly */ if (currentBytes % 333333 < 9000) { - progressListener.onProgress(urlString, currentBytes, totalBytes); + progressListener.onProgress(currentBytes, totalBytes); } } return super.read(buffer, byteOffset, byteCount); diff --git a/app/src/main/java/org/fdroid/fdroid/ProgressListener.java b/app/src/main/java/org/fdroid/fdroid/ProgressListener.java index dc9fbcbdb..e45cb7356 100644 --- a/app/src/main/java/org/fdroid/fdroid/ProgressListener.java +++ b/app/src/main/java/org/fdroid/fdroid/ProgressListener.java @@ -19,6 +19,6 @@ import java.net.URL; */ public interface ProgressListener { - void onProgress(String urlString, long bytesRead, long totalBytes); + void onProgress(long bytesRead, long totalBytes); } diff --git a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java index 04b215543..9fe3ca529 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java +++ b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java @@ -207,7 +207,7 @@ public abstract class Downloader { @Override public void run() { if (downloaderProgressListener != null) { - downloaderProgressListener.onProgress(urlString, bytesRead, totalBytes); + downloaderProgressListener.onProgress(bytesRead, totalBytes); } } }; diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index efbd57a45..0bfd358ba 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -207,7 +207,7 @@ public class DownloaderService extends Service { downloader = DownloaderFactory.create(this, uri, localFile); downloader.setListener(new ProgressListener() { @Override - public void onProgress(String urlString, long bytesRead, long totalBytes) { + public void onProgress(long bytesRead, long totalBytes) { Intent intent = new Intent(Downloader.ACTION_PROGRESS); intent.setData(uri); intent.putExtra(Downloader.EXTRA_BYTES_READ, bytesRead); From 04298f8886b2e857132a3bc9fed4cba9c755ee23 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 26 Mar 2019 17:23:25 +0100 Subject: [PATCH 06/14] DownloaderService: only broadcast progress when it actually changes On a slow download, this could send like 100+ updates even though no more data had been received. closes #1742 --- app/src/main/java/org/fdroid/fdroid/net/Downloader.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java index 9fe3ca529..f37a6dcd6 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java +++ b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java @@ -204,10 +204,16 @@ public abstract class Downloader { * Send progress updates on a timer to avoid flooding receivers with pointless events. */ private final TimerTask progressTask = new TimerTask() { + private long lastBytesRead = Long.MIN_VALUE; + private long lastTotalBytes = Long.MIN_VALUE; + @Override public void run() { - if (downloaderProgressListener != null) { + if (downloaderProgressListener != null + && (bytesRead != lastBytesRead || totalBytes != lastTotalBytes)) { downloaderProgressListener.onProgress(bytesRead, totalBytes); + lastBytesRead = bytesRead; + lastTotalBytes = totalBytes; } } }; From 288577407df0042fe40cb9eabb6736218bae95a5 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 26 Mar 2019 22:52:24 +0100 Subject: [PATCH 07/14] move towards only using canonical URLs in InstallManagerService Only DownloaderService really needs to know about the mirror tricks, the rest of the process should only ever use the canonical URL to keep things simple. --- .../installer/InstallManagerService.java | 34 +++--------- .../fdroid/fdroid/net/DownloaderService.java | 53 +++++++++++++++---- 2 files changed, 50 insertions(+), 37 deletions(-) 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 2329d045b..184c30bff 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -11,7 +11,6 @@ import android.content.pm.PackageInfo; import android.net.Uri; import android.os.IBinder; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.util.Log; @@ -213,7 +212,7 @@ public class InstallManagerService extends Service { long apkFileSize = apkFilePath.length(); if (!apkFilePath.exists() || apkFileSize < apk.size) { Utils.debugLog(TAG, "download " + urlString + " " + apkFilePath); - DownloaderService.queue(this, switchUrlToNewMirror(urlString, apk.repoId), apk.repoId, urlString); + DownloaderService.queueUsingRandomMirror(this, apk.repoId, urlString); } else if (ApkCache.apkIsCached(apkFilePath, apk)) { Utils.debugLog(TAG, "skip download, we have it, straight to install " + urlString + " " + apkFilePath); sendBroadcast(intent.getData(), Downloader.ACTION_STARTED, apkFilePath); @@ -221,7 +220,7 @@ public class InstallManagerService extends Service { } else { Utils.debugLog(TAG, "delete and download again " + urlString + " " + apkFilePath); apkFilePath.delete(); - DownloaderService.queue(this, switchUrlToNewMirror(urlString, apk.repoId), apk.repoId, urlString); + DownloaderService.queueUsingRandomMirror(this, apk.repoId, urlString); } return START_REDELIVER_INTENT; // if killed before completion, retry Intent @@ -234,24 +233,6 @@ public class InstallManagerService extends Service { localBroadcastManager.sendBroadcast(intent); } - /** - * Tries to return a version of {@code urlString} from a mirror, if there - * is an error, it just returns {@code urlString}. - * - * @see FDroidApp#getNewMirrorOnError(String, org.fdroid.fdroid.data.Repo) - */ - public String getNewMirrorOnError(@Nullable String urlString, long repoId) { - try { - return FDroidApp.getNewMirrorOnError(urlString, RepoProvider.Helper.findById(this, repoId)); - } catch (IOException e) { - return urlString; - } - } - - public String switchUrlToNewMirror(@Nullable String urlString, long repoId) { - return FDroidApp.switchUrlToNewMirror(urlString, RepoProvider.Helper.findById(this, repoId)); - } - /** * Check if any OBB files are available, and if so, download and install them. This * also deletes any obsolete OBB files, per the spec, since there can be only one @@ -310,13 +291,13 @@ public class InstallManagerService extends Service { } else if (Downloader.ACTION_INTERRUPTED.equals(action)) { localBroadcastManager.unregisterReceiver(this); } else if (Downloader.ACTION_CONNECTION_FAILED.equals(action)) { - DownloaderService.queue(context, getNewMirrorOnError(urlString, 0), 0, urlString); + DownloaderService.queueUsingDifferentMirror(context, 0, urlString); } else { throw new RuntimeException("intent action not handled!"); } } }; - DownloaderService.queue(this, switchUrlToNewMirror(obbUrlString, 0), 0, obbUrlString); + DownloaderService.queueUsingRandomMirror(this, 0, obbUrlString); localBroadcastManager.registerReceiver(downloadReceiver, DownloaderService.getIntentFilter(obbUrlString)); } @@ -337,7 +318,6 @@ public class InstallManagerService extends Service { Uri downloadUri = intent.getData(); String urlString = downloadUri.toString(); long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); - String mirrorUrlString = intent.getStringExtra(Downloader.EXTRA_MIRROR_URL); switch (intent.getAction()) { case Downloader.ACTION_STARTED: @@ -357,7 +337,8 @@ public class InstallManagerService extends Service { File localFile = new File(intent.getStringExtra(Downloader.EXTRA_DOWNLOAD_PATH)); Uri localApkUri = Uri.fromFile(localFile); - Utils.debugLog(TAG, "download completed of " + mirrorUrlString + " to " + localApkUri); + Utils.debugLog(TAG, "download completed of " + + intent.getStringExtra(Downloader.EXTRA_MIRROR_URL) + " to " + localApkUri); appUpdateStatusManager.updateApk(urlString, AppUpdateStatusManager.Status.ReadyToInstall, null); localBroadcastManager.unregisterReceiver(this); @@ -374,7 +355,8 @@ public class InstallManagerService extends Service { break; case Downloader.ACTION_CONNECTION_FAILED: try { - String currentUrlString = FDroidApp.getNewMirrorOnError(mirrorUrlString, + String currentUrlString = FDroidApp.getNewMirrorOnError( + intent.getStringExtra(Downloader.EXTRA_MIRROR_URL), RepoProvider.Helper.findById(InstallManagerService.this, repoId)); DownloaderService.queue(context, currentUrlString, repoId, urlString); DownloaderService.setTimeout(FDroidApp.getTimeout()); diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index 0bfd358ba..19db341cb 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -32,9 +32,11 @@ import android.os.Process; import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.util.Log; +import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.ProgressListener; import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; +import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.data.SanitizedFile; import org.fdroid.fdroid.installer.ApkCache; @@ -277,25 +279,54 @@ public class DownloaderService extends Service { *

* All notifications are sent as an {@link Intent} via local broadcasts to be received by * - * @param context this app's {@link Context} - * @param mirrorUrlString The URL to add to the download queue - * @param repoId the database ID number representing one repo - * @param canonicalUrl the URL used as the unique ID throughout F-Droid + * @param context this app's {@link Context} + * @param mirrorUrl The URL to add to the download queue + * @param repoId the database ID number representing one repo + * @param canonicalUrl the URL used as the unique ID throughout F-Droid * @see #cancel(Context, String) */ - public static void queue(Context context, String mirrorUrlString, long repoId, String canonicalUrl) { - if (TextUtils.isEmpty(mirrorUrlString)) { + public static void queue(Context context, String mirrorUrl, long repoId, String canonicalUrl) { + if (TextUtils.isEmpty(mirrorUrl)) { return; } - Utils.debugLog(TAG, "Preparing " + mirrorUrlString + " to go into the download queue"); + Utils.debugLog(TAG, "Preparing " + mirrorUrl + " to go into the download queue"); Intent intent = new Intent(context, DownloaderService.class); intent.setAction(ACTION_QUEUE); - intent.setData(Uri.parse(mirrorUrlString)); + intent.setData(Uri.parse(mirrorUrl)); intent.putExtra(Downloader.EXTRA_REPO_ID, repoId); intent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUrl); context.startService(intent); } + /** + * Add a package to the download queue, choosing a random mirror to + * download from. + * + * @param canonicalUrl the URL used as the unique ID throughout F-Droid, + * needed here to support canceling active downloads + */ + public static void queueUsingRandomMirror(Context context, long repoId, String canonicalUrl) { + String mirrorUrl = FDroidApp.switchUrlToNewMirror(canonicalUrl, + RepoProvider.Helper.findById(context, repoId)); + queue(context, mirrorUrl, repoId, canonicalUrl); + } + + /** + * Tries to return a version of {@code urlString} from a mirror, if there + * is an error, it just returns {@code urlString}. + * + * @see FDroidApp#getNewMirrorOnError(String, org.fdroid.fdroid.data.Repo) + */ + public static void queueUsingDifferentMirror(Context context, long repoId, String canonicalUrl) { + try { + String mirrorUrl = FDroidApp.getNewMirrorOnError(canonicalUrl, + RepoProvider.Helper.findById(context, repoId)); + queue(context, mirrorUrl, repoId, canonicalUrl); + } catch (IOException e) { + queue(context, canonicalUrl, repoId, canonicalUrl); + } + } + /** * Remove a URL to the download queue, even if it is currently downloading. *

@@ -345,10 +376,10 @@ public class DownloaderService extends Service { /** * Get a prepared {@link IntentFilter} for use for matching this service's action events. * - * @param urlString The full file URL to match. + * @param canonicalUrl the URL used as the unique ID for the specific package */ - public static IntentFilter getIntentFilter(String urlString) { - Uri uri = Uri.parse(urlString); + public static IntentFilter getIntentFilter(String canonicalUrl) { + Uri uri = Uri.parse(canonicalUrl); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Downloader.ACTION_STARTED); intentFilter.addAction(Downloader.ACTION_PROGRESS); From 7f22c3c221d9fb09e882f7536e970cd1da558b83 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 27 Mar 2019 12:04:25 +0100 Subject: [PATCH 08/14] DownloaderService: convert String to Uri to avoid repeated parsing This parses the String into a Uri once per Intent, rather than once per broadcast. The Uri instance is also nicer to work with, since it is the native URL format for Intents. It should make the progress updates a bit more efficient also. fdroid/fdroidclient#1742 --- .../java/org/fdroid/fdroid/installer/ApkCache.java | 10 ++++++++-- .../java/org/fdroid/fdroid/net/DownloaderService.java | 10 +++++----- 2 files changed, 13 insertions(+), 7 deletions(-) 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 c1c15d117..747fcd7c9 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/ApkCache.java @@ -113,10 +113,16 @@ public class ApkCache { } /** - * Get the full path for where an APK URL will be downloaded into. + * Get the full path for where an package URL will be downloaded into. */ public static SanitizedFile getApkDownloadPath(Context context, String urlString) { - Uri uri = Uri.parse(urlString); + return getApkDownloadPath(context, Uri.parse(urlString)); + } + + /** + * Get the full path for where an package URL will be downloaded into. + */ + public static SanitizedFile getApkDownloadPath(Context context, Uri uri) { File dir = new File(getApkCacheDir(context), uri.getHost() + "-" + uri.getPort()); if (!dir.exists()) { dir.mkdirs(); diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index 19db341cb..9d7a1a970 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -200,8 +200,8 @@ public class DownloaderService extends Service { */ private void handleIntent(Intent intent) { final Uri uri = intent.getData(); - long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); - String canonicalUrl = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); + final long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); + final Uri canonicalUrl = Uri.parse(intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL)); final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, canonicalUrl); sendBroadcast(uri, Downloader.ACTION_STARTED, localFile, repoId, canonicalUrl); @@ -249,7 +249,7 @@ public class DownloaderService extends Service { sendBroadcast(uri, action, null, null); } - private void sendBroadcast(Uri uri, String action, File file, long repoId, String canonicalUrl) { + private void sendBroadcast(Uri uri, String action, File file, long repoId, Uri canonicalUrl) { sendBroadcast(uri, action, file, null, repoId, canonicalUrl); } @@ -258,10 +258,10 @@ public class DownloaderService extends Service { } private void sendBroadcast(Uri uri, String action, File file, String errorMessage, long repoId, - String canonicalUrl) { + Uri canonicalUrl) { Intent intent = new Intent(action); if (canonicalUrl != null) { - intent.setData(Uri.parse(canonicalUrl)); + intent.setData(canonicalUrl); } if (file != null) { intent.putExtra(Downloader.EXTRA_DOWNLOAD_PATH, file.getAbsolutePath()); From 3a5f96e0b3534a84bae1eec58eca47e6fad79ddf Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 27 Mar 2019 12:05:45 +0100 Subject: [PATCH 09/14] DownloaderService: use canonical URL to fix progress updates The download URL is not the unique ID, the canonical URL is. closes #1736 --- app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index 9d7a1a970..b4201e486 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -211,7 +211,7 @@ public class DownloaderService extends Service { @Override public void onProgress(long bytesRead, long totalBytes) { Intent intent = new Intent(Downloader.ACTION_PROGRESS); - intent.setData(uri); + intent.setData(canonicalUrl); intent.putExtra(Downloader.EXTRA_BYTES_READ, bytesRead); intent.putExtra(Downloader.EXTRA_TOTAL_BYTES, totalBytes); localBroadcastManager.sendBroadcast(intent); From 3378c0a333bb84d55aeb0c608d9b40ed32b2b0f3 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 27 Mar 2019 13:13:53 +0100 Subject: [PATCH 10/14] rename Canonical vs. Download URL in InstallManagerService process AppUpdateStatusManager and InstallManagerService should be using only the Canonical URL of the package since that is the global unique ID. The actual URL used to download it needs to be isolated in DownloaderService, which can entirely manage the mirror selection process. This is just a bunch of renaming to make this all clearer. --- .../fdroid/views/swap/SwapAppsView.java | 4 +- .../views/swap/SwapWorkflowActivity.java | 3 +- .../fdroid/fdroid/AppUpdateStatusManager.java | 13 ++- .../fdroid/NotificationBroadcastReceiver.java | 8 +- .../fdroid/installer/DefaultInstaller.java | 6 +- .../installer/DefaultInstallerActivity.java | 17 ++-- .../fdroid/installer/FileInstaller.java | 10 +- .../installer/FileInstallerActivity.java | 24 ++--- .../installer/InstallManagerService.java | 95 ++++++++++--------- .../fdroid/fdroid/installer/Installer.java | 58 ++++++----- .../fdroid/installer/InstallerService.java | 21 ++-- .../fdroid/installer/PrivilegedInstaller.java | 10 +- .../fdroid/fdroid/net/DownloaderService.java | 27 +++--- .../fdroid/views/AppDetailsActivity.java | 2 +- .../views/apps/AppListItemController.java | 10 +- .../items/KnownVulnAppListItemController.java | 9 +- 16 files changed, 170 insertions(+), 147 deletions(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java index 7ad2f38eb..076d4ec45 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java +++ b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java @@ -314,10 +314,8 @@ public class SwapAppsView extends ListView implements } if (apk != null) { - String urlString = apk.getCanonicalUrl(); - // TODO unregister receivers? or will they just die with this instance - IntentFilter downloadFilter = DownloaderService.getIntentFilter(urlString); + IntentFilter downloadFilter = DownloaderService.getIntentFilter(apk.getCanonicalUrl()); localBroadcastManager.registerReceiver(downloadReceiver, downloadFilter); } diff --git a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java index a8a426db9..c55d773b6 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -836,9 +836,8 @@ public class SwapWorkflowActivity extends AppCompatActivity { } public void install(@NonNull final App app, @NonNull final Apk apk) { - Uri downloadUri = Uri.parse(apk.getCanonicalUrl()); localBroadcastManager.registerReceiver(installReceiver, - Installer.getInstallIntentFilter(downloadUri)); + Installer.getInstallIntentFilter(apk.getCanonicalUrl())); InstallManagerService.queue(this, app, apk); } diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java index a1372c619..6db802467 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java +++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java @@ -129,7 +129,7 @@ public final class AppUpdateStatusManager { /** * @return the unique ID used to represent this specific package's install process - * also known as {@code urlString}. + * also known as {@code canonicalUrl}. * @see org.fdroid.fdroid.installer.InstallManagerService */ public String getCanonicalUrl() { @@ -225,9 +225,9 @@ public final class AppUpdateStatusManager { } @Nullable - public AppUpdateStatus get(String key) { + public AppUpdateStatus get(String canonicalUrl) { synchronized (appMapping) { - return appMapping.get(key); + return appMapping.get(canonicalUrl); } } @@ -420,16 +420,15 @@ public final class AppUpdateStatusManager { /** * @param errorText If null, then it is likely because the user cancelled the download. */ - // TODO should url actually be canonicalUrl? - public void setDownloadError(String url, @Nullable String errorText) { + public void setDownloadError(String canonicalUrl, @Nullable String errorText) { synchronized (appMapping) { - AppUpdateStatus entry = appMapping.get(url); + AppUpdateStatus entry = appMapping.get(canonicalUrl); if (entry != null) { entry.status = Status.DownloadInterrupted; entry.errorText = errorText; entry.intent = null; notifyChange(entry, true); - removeApk(url); + removeApk(canonicalUrl); } } } diff --git a/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java b/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java index d562a0484..a93982cf5 100644 --- a/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java +++ b/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java @@ -14,7 +14,7 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context); - String notificationKey = intent.getStringExtra(NotificationHelper.EXTRA_NOTIFICATION_KEY); + String canonicalUrl = intent.getStringExtra(NotificationHelper.EXTRA_NOTIFICATION_KEY); switch (intent.getAction()) { case NotificationHelper.BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED: manager.clearAllUpdates(); @@ -25,13 +25,13 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver { case NotificationHelper.BROADCAST_NOTIFICATIONS_UPDATE_CLEARED: // If clearing apps in state "InstallError" (like when auto-cancelling) we // remove them from the status manager entirely. - AppUpdateStatusManager.AppUpdateStatus appUpdateStatus = manager.get(notificationKey); + AppUpdateStatusManager.AppUpdateStatus appUpdateStatus = manager.get(canonicalUrl); if (appUpdateStatus != null && appUpdateStatus.status == AppUpdateStatusManager.Status.InstallError) { - manager.removeApk(notificationKey); + manager.removeApk(canonicalUrl); } break; case NotificationHelper.BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED: - manager.removeApk(notificationKey); + manager.removeApk(canonicalUrl); break; } } diff --git a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java index 70c23e054..af3535ba5 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java @@ -43,11 +43,11 @@ public class DefaultInstaller extends Installer { } @Override - protected void installPackageInternal(Uri localApkUri, Uri downloadUri) { + protected void installPackageInternal(Uri localApkUri, Uri canonicalUri) { Intent installIntent = new Intent(context, DefaultInstallerActivity.class); installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE); - installIntent.putExtra(Installer.EXTRA_DOWNLOAD_URI, downloadUri); + installIntent.putExtra(Installer.EXTRA_DOWNLOAD_URI, canonicalUri); installIntent.putExtra(Installer.EXTRA_APK, apk); installIntent.setData(localApkUri); @@ -57,7 +57,7 @@ public class DefaultInstaller extends Installer { installIntent, PendingIntent.FLAG_UPDATE_CURRENT); - sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_USER_INTERACTION, + sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_USER_INTERACTION, installPendingIntent); } diff --git a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java index 322350c29..a0e32e6c9 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java @@ -48,7 +48,10 @@ public class DefaultInstallerActivity extends FragmentActivity { private static final int REQUEST_CODE_INSTALL = 0; private static final int REQUEST_CODE_UNINSTALL = 1; - private Uri downloadUri; + /** + * @see InstallManagerService + */ + private Uri canonicalUri; // for the broadcasts private DefaultInstaller installer; @@ -63,7 +66,7 @@ public class DefaultInstallerActivity extends FragmentActivity { installer = new DefaultInstaller(this, apk); if (ACTION_INSTALL_PACKAGE.equals(action)) { Uri localApkUri = intent.getData(); - downloadUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); + canonicalUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); installPackage(localApkUri); } else if (ACTION_UNINSTALL_PACKAGE.equals(action)) { uninstallPackage(apk.packageName); @@ -120,7 +123,7 @@ public class DefaultInstallerActivity extends FragmentActivity { startActivityForResult(intent, REQUEST_CODE_INSTALL); } catch (ActivityNotFoundException e) { Log.e(TAG, "ActivityNotFoundException", e); - installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED, + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED, "This Android rom does not support ACTION_INSTALL_PACKAGE!"); finish(); } @@ -169,23 +172,23 @@ public class DefaultInstallerActivity extends FragmentActivity { * never executed on Androids < 4.0 */ if (Build.VERSION.SDK_INT < 14) { - installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_COMPLETE); + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_COMPLETE); break; } switch (resultCode) { case Activity.RESULT_OK: - installer.sendBroadcastInstall(downloadUri, + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_COMPLETE); break; case Activity.RESULT_CANCELED: - installer.sendBroadcastInstall(downloadUri, + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED); break; case Activity.RESULT_FIRST_USER: default: // AOSP returns Activity.RESULT_FIRST_USER on error - installer.sendBroadcastInstall(downloadUri, + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED, getString(R.string.install_error_unknown)); break; diff --git a/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java index 01bf38d3d..63975208a 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java @@ -44,15 +44,15 @@ public class FileInstaller extends Installer { } @Override - public void installPackage(Uri localApkUri, Uri downloadUri) { - installPackageInternal(localApkUri, downloadUri); + public void installPackage(Uri localApkUri, Uri canonicalUri) { + installPackageInternal(localApkUri, canonicalUri); } @Override - protected void installPackageInternal(Uri localApkUri, Uri downloadUri) { + protected void installPackageInternal(Uri localApkUri, Uri canonicalUri) { Intent installIntent = new Intent(context, FileInstallerActivity.class); installIntent.setAction(FileInstallerActivity.ACTION_INSTALL_FILE); - installIntent.putExtra(Installer.EXTRA_DOWNLOAD_URI, downloadUri); + installIntent.putExtra(Installer.EXTRA_DOWNLOAD_URI, canonicalUri); installIntent.putExtra(Installer.EXTRA_APK, apk); installIntent.setData(localApkUri); @@ -62,7 +62,7 @@ public class FileInstaller extends Installer { installIntent, PendingIntent.FLAG_UPDATE_CURRENT); - sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_USER_INTERACTION, + sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_USER_INTERACTION, installPendingIntent); } diff --git a/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java b/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java index 9bc3db7b8..5d7d1ddb3 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java @@ -13,7 +13,6 @@ import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.view.ContextThemeWrapper; import android.widget.Toast; - import org.apache.commons.io.FileUtils; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.R; @@ -40,7 +39,10 @@ public class FileInstallerActivity extends FragmentActivity { private Apk apk; private Uri localApkUri; - private Uri downloadUri; + /** + * @see InstallManagerService + */ + private Uri canonicalUri; private int act = 0; @@ -51,12 +53,12 @@ public class FileInstallerActivity extends FragmentActivity { Intent intent = getIntent(); String action = intent.getAction(); localApkUri = intent.getData(); - downloadUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); + canonicalUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); apk = intent.getParcelableExtra(Installer.EXTRA_APK); installer = new FileInstaller(this, apk); if (ACTION_INSTALL_FILE.equals(action)) { if (hasStoragePermission()) { - installPackage(localApkUri, downloadUri, apk); + installPackage(localApkUri, canonicalUri, apk); } else { requestPermission(); act = 1; @@ -110,7 +112,7 @@ public class FileInstallerActivity extends FragmentActivity { .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (act == 1) { - installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED); + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED); } else if (act == 2) { installer.sendBroadcastUninstall(Installer.ACTION_UNINSTALL_INTERRUPTED); } @@ -129,13 +131,13 @@ public class FileInstallerActivity extends FragmentActivity { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (act == 1) { - installPackage(localApkUri, downloadUri, apk); + installPackage(localApkUri, canonicalUri, apk); } else if (act == 2) { uninstallPackage(apk); } } else { if (act == 1) { - installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED); + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED); } else if (act == 2) { installer.sendBroadcastUninstall(Installer.ACTION_UNINSTALL_INTERRUPTED); } @@ -144,7 +146,7 @@ public class FileInstallerActivity extends FragmentActivity { } } - private void installPackage(Uri localApkUri, Uri downloadUri, Apk apk) { + private void installPackage(Uri localApkUri, Uri canonicalUri, Apk apk) { Utils.debugLog(TAG, "Installing: " + localApkUri.getPath()); File path = apk.getMediaInstallPath(activity.getApplicationContext()); path.mkdirs(); @@ -152,15 +154,15 @@ public class FileInstallerActivity extends FragmentActivity { FileUtils.copyFileToDirectory(new File(localApkUri.getPath()), path); } catch (IOException e) { Utils.debugLog(TAG, "Failed to copy: " + e.getMessage()); - installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED); + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED); } if (apk.isMediaInstalled(activity.getApplicationContext())) { // Copying worked Utils.debugLog(TAG, "Copying worked: " + localApkUri.getPath()); Toast.makeText(this, String.format(this.getString(R.string.app_installed_media), path.toString()), Toast.LENGTH_LONG).show(); - installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_COMPLETE); + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_COMPLETE); } else { - installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED); + installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED); } finish(); } 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 184c30bff..78fae9b1c 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -65,7 +65,7 @@ import java.io.IOException; * APK on different servers, signed by different keys, or even different builds. *

    *
  • for a {@link Uri} ID, use {@code Uri}, {@link Intent#getData()} - *
  • for a {@code String} ID, use {@code urlString}, {@link Uri#toString()}, or + *
  • for a {@code String} ID, use {@code canonicalUrl}, {@link Uri#toString()}, or * {@link Intent#getDataString()} *
  • for an {@code int} ID, use {@link String#hashCode()} or {@link Uri#hashCode()} *

@@ -146,24 +146,24 @@ public class InstallManagerService extends Service { public int onStartCommand(Intent intent, int flags, int startId) { Utils.debugLog(TAG, "onStartCommand " + intent); - String urlString = intent.getDataString(); - if (TextUtils.isEmpty(urlString)) { - Utils.debugLog(TAG, "empty urlString, nothing to do"); + String canonicalUrl = intent.getDataString(); + if (TextUtils.isEmpty(canonicalUrl)) { + Utils.debugLog(TAG, "empty canonicalUrl, nothing to do"); return START_NOT_STICKY; } String action = intent.getAction(); if (ACTION_CANCEL.equals(action)) { - DownloaderService.cancel(this, urlString); - Apk apk = appUpdateStatusManager.getApk(urlString); + DownloaderService.cancel(this, canonicalUrl); + Apk apk = appUpdateStatusManager.getApk(canonicalUrl); if (apk != null) { DownloaderService.cancel(this, apk.getPatchObbUrl()); DownloaderService.cancel(this, apk.getMainObbUrl()); } return START_NOT_STICKY; } else if (ACTION_INSTALL.equals(action)) { - if (!isPendingInstall(urlString)) { + if (!isPendingInstall(canonicalUrl)) { Log.i(TAG, "Ignoring INSTALL that is not Pending Install: " + intent); return START_NOT_STICKY; } @@ -173,14 +173,14 @@ public class InstallManagerService extends Service { } if (!intent.hasExtra(EXTRA_APP) || !intent.hasExtra(EXTRA_APK)) { - Utils.debugLog(TAG, urlString + " did not include both an App and Apk instance, ignoring"); + Utils.debugLog(TAG, canonicalUrl + " did not include both an App and Apk instance, ignoring"); return START_NOT_STICKY; } if ((flags & START_FLAG_REDELIVERY) == START_FLAG_REDELIVERY - && !DownloaderService.isQueuedOrActive(urlString)) { - Utils.debugLog(TAG, urlString + " finished downloading while InstallManagerService was killed."); - appUpdateStatusManager.removeApk(urlString); + && !DownloaderService.isQueuedOrActive(canonicalUrl)) { + Utils.debugLog(TAG, canonicalUrl + " finished downloading while InstallManagerService was killed."); + appUpdateStatusManager.removeApk(canonicalUrl); return START_NOT_STICKY; } @@ -204,23 +204,23 @@ public class InstallManagerService extends Service { appUpdateStatusManager.addApk(apk, AppUpdateStatusManager.Status.Downloading, null); - registerPackageDownloaderReceivers(urlString); - getObb(urlString, apk.getMainObbUrl(), apk.getMainObbFile(), apk.obbMainFileSha256); - getObb(urlString, apk.getPatchObbUrl(), apk.getPatchObbFile(), apk.obbPatchFileSha256); + registerPackageDownloaderReceivers(canonicalUrl); + getObb(canonicalUrl, apk.getMainObbUrl(), apk.getMainObbFile(), apk.obbMainFileSha256); + getObb(canonicalUrl, apk.getPatchObbUrl(), apk.getPatchObbFile(), apk.obbPatchFileSha256); File apkFilePath = ApkCache.getApkDownloadPath(this, apk.getCanonicalUrl()); long apkFileSize = apkFilePath.length(); if (!apkFilePath.exists() || apkFileSize < apk.size) { - Utils.debugLog(TAG, "download " + urlString + " " + apkFilePath); - DownloaderService.queueUsingRandomMirror(this, apk.repoId, urlString); + Utils.debugLog(TAG, "download " + canonicalUrl + " " + apkFilePath); + DownloaderService.queueUsingRandomMirror(this, apk.repoId, canonicalUrl); } else if (ApkCache.apkIsCached(apkFilePath, apk)) { - Utils.debugLog(TAG, "skip download, we have it, straight to install " + urlString + " " + apkFilePath); + Utils.debugLog(TAG, "skip download, we have it, straight to install " + canonicalUrl + " " + apkFilePath); sendBroadcast(intent.getData(), Downloader.ACTION_STARTED, apkFilePath); sendBroadcast(intent.getData(), Downloader.ACTION_COMPLETE, apkFilePath); } else { - Utils.debugLog(TAG, "delete and download again " + urlString + " " + apkFilePath); + Utils.debugLog(TAG, "delete and download again " + canonicalUrl + " " + apkFilePath); apkFilePath.delete(); - DownloaderService.queueUsingRandomMirror(this, apk.repoId, urlString); + DownloaderService.queueUsingRandomMirror(this, apk.repoId, canonicalUrl); } return START_REDELIVER_INTENT; // if killed before completion, retry Intent @@ -240,7 +240,7 @@ public class InstallManagerService extends Service { * * @see APK Expansion Files */ - private void getObb(final String urlString, String obbUrlString, + private void getObb(final String canonicalUrl, String obbUrlString, final File obbDestFile, final String hash) { if (obbDestFile == null || obbDestFile.exists() || TextUtils.isEmpty(obbUrlString)) { return; @@ -259,7 +259,7 @@ public class InstallManagerService extends Service { long bytesRead = intent.getLongExtra(Downloader.EXTRA_BYTES_READ, 0); long totalBytes = intent.getLongExtra(Downloader.EXTRA_TOTAL_BYTES, 0); - appUpdateStatusManager.updateApkProgress(urlString, totalBytes, bytesRead); + appUpdateStatusManager.updateApkProgress(canonicalUrl, totalBytes, bytesRead); } else if (Downloader.ACTION_COMPLETE.equals(action)) { localBroadcastManager.unregisterReceiver(this); File localFile = new File(intent.getStringExtra(Downloader.EXTRA_DOWNLOAD_PATH)); @@ -291,7 +291,7 @@ public class InstallManagerService extends Service { } else if (Downloader.ACTION_INTERRUPTED.equals(action)) { localBroadcastManager.unregisterReceiver(this); } else if (Downloader.ACTION_CONNECTION_FAILED.equals(action)) { - DownloaderService.queueUsingDifferentMirror(context, 0, urlString); + DownloaderService.queueUsingDifferentMirror(context, 0, canonicalUrl); } else { throw new RuntimeException("intent action not handled!"); } @@ -304,9 +304,9 @@ public class InstallManagerService extends Service { /** * Register a {@link BroadcastReceiver} for tracking download progress for a - * give {@code urlString}. There can be multiple of these registered at a time. + * give {@code canonicalUrl}. There can be multiple of these registered at a time. */ - private void registerPackageDownloaderReceivers(String urlString) { + private void registerPackageDownloaderReceivers(String canonicalUrl) { BroadcastReceiver downloadReceiver = new BroadcastReceiver() { @Override @@ -315,8 +315,8 @@ public class InstallManagerService extends Service { localBroadcastManager.unregisterReceiver(this); return; } - Uri downloadUri = intent.getData(); - String urlString = downloadUri.toString(); + Uri canonicalUri = intent.getData(); + String canonicalUrl = intent.getDataString(); long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); switch (intent.getAction()) { @@ -324,14 +324,15 @@ public class InstallManagerService extends Service { // App should currently be in the "PendingDownload" state, so this changes it to "Downloading". Intent intentObject = new Intent(context, InstallManagerService.class); intentObject.setAction(ACTION_CANCEL); - intentObject.setData(downloadUri); + intentObject.setData(canonicalUri); PendingIntent action = PendingIntent.getService(context, 0, intentObject, 0); - appUpdateStatusManager.updateApk(urlString, AppUpdateStatusManager.Status.Downloading, action); + appUpdateStatusManager.updateApk(canonicalUrl, + AppUpdateStatusManager.Status.Downloading, action); break; case Downloader.ACTION_PROGRESS: long bytesRead = intent.getLongExtra(Downloader.EXTRA_BYTES_READ, 0); long totalBytes = intent.getLongExtra(Downloader.EXTRA_TOTAL_BYTES, 0); - appUpdateStatusManager.updateApkProgress(urlString, totalBytes, bytesRead); + appUpdateStatusManager.updateApkProgress(canonicalUrl, totalBytes, bytesRead); break; case Downloader.ACTION_COMPLETE: File localFile = new File(intent.getStringExtra(Downloader.EXTRA_DOWNLOAD_PATH)); @@ -339,29 +340,33 @@ public class InstallManagerService extends Service { Utils.debugLog(TAG, "download completed of " + intent.getStringExtra(Downloader.EXTRA_MIRROR_URL) + " to " + localApkUri); - appUpdateStatusManager.updateApk(urlString, AppUpdateStatusManager.Status.ReadyToInstall, null); + appUpdateStatusManager.updateApk(canonicalUrl, + AppUpdateStatusManager.Status.ReadyToInstall, null); localBroadcastManager.unregisterReceiver(this); - registerInstallReceiver(downloadUri); + registerInstallReceiver(canonicalUrl); - Apk apk = appUpdateStatusManager.getApk(urlString); + Apk apk = appUpdateStatusManager.getApk(canonicalUrl); if (apk != null) { - InstallerService.install(context, localApkUri, downloadUri, apk); + InstallerService.install(context, localApkUri, canonicalUri, apk); } break; case Downloader.ACTION_INTERRUPTED: - appUpdateStatusManager.setDownloadError(urlString, intent.getStringExtra(Downloader.EXTRA_ERROR_MESSAGE)); + appUpdateStatusManager.setDownloadError(canonicalUrl, + intent.getStringExtra(Downloader.EXTRA_ERROR_MESSAGE)); localBroadcastManager.unregisterReceiver(this); break; case Downloader.ACTION_CONNECTION_FAILED: + // TODO move this logic into DownloaderService to hide the mirror URL stuff from this class try { String currentUrlString = FDroidApp.getNewMirrorOnError( intent.getStringExtra(Downloader.EXTRA_MIRROR_URL), RepoProvider.Helper.findById(InstallManagerService.this, repoId)); - DownloaderService.queue(context, currentUrlString, repoId, urlString); + DownloaderService.queue(context, currentUrlString, repoId, canonicalUrl); DownloaderService.setTimeout(FDroidApp.getTimeout()); } catch (IOException e) { - appUpdateStatusManager.setDownloadError(urlString, intent.getStringExtra(Downloader.EXTRA_ERROR_MESSAGE)); + appUpdateStatusManager.setDownloadError(canonicalUrl, + intent.getStringExtra(Downloader.EXTRA_ERROR_MESSAGE)); localBroadcastManager.unregisterReceiver(this); } break; @@ -372,14 +377,14 @@ public class InstallManagerService extends Service { }; localBroadcastManager.registerReceiver(downloadReceiver, - DownloaderService.getIntentFilter(urlString)); + DownloaderService.getIntentFilter(canonicalUrl)); } /** * Register a {@link BroadcastReceiver} for tracking install progress for a * give {@link Uri}. There can be multiple of these registered at a time. */ - private void registerInstallReceiver(Uri downloadUri) { + private void registerInstallReceiver(String canonicalUrl) { BroadcastReceiver installReceiver = new BroadcastReceiver() { @Override @@ -388,15 +393,17 @@ public class InstallManagerService extends Service { localBroadcastManager.unregisterReceiver(this); return; } - String downloadUrl = intent.getDataString(); + String canonicalUrl = intent.getDataString(); Apk apk; switch (intent.getAction()) { case Installer.ACTION_INSTALL_STARTED: - appUpdateStatusManager.updateApk(downloadUrl, AppUpdateStatusManager.Status.Installing, null); + appUpdateStatusManager.updateApk(canonicalUrl, + AppUpdateStatusManager.Status.Installing, null); break; case Installer.ACTION_INSTALL_COMPLETE: - appUpdateStatusManager.updateApk(downloadUrl, AppUpdateStatusManager.Status.Installed, null); - Apk apkComplete = appUpdateStatusManager.getApk(downloadUrl); + appUpdateStatusManager.updateApk(canonicalUrl, + AppUpdateStatusManager.Status.Installed, null); + Apk apkComplete = appUpdateStatusManager.getApk(canonicalUrl); if (apkComplete != null && apkComplete.isApk()) { try { @@ -414,7 +421,7 @@ public class InstallManagerService extends Service { if (!TextUtils.isEmpty(errorMessage)) { appUpdateStatusManager.setApkError(apk, errorMessage); } else { - appUpdateStatusManager.removeApk(downloadUrl); + appUpdateStatusManager.removeApk(canonicalUrl); } localBroadcastManager.unregisterReceiver(this); break; @@ -430,7 +437,7 @@ public class InstallManagerService extends Service { }; localBroadcastManager.registerReceiver(installReceiver, - Installer.getInstallIntentFilter(downloadUri)); + Installer.getInstallIntentFilter(canonicalUrl)); } /** diff --git a/app/src/main/java/org/fdroid/fdroid/installer/Installer.java b/app/src/main/java/org/fdroid/fdroid/installer/Installer.java index 40b2e1775..9b646a988 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/Installer.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/Installer.java @@ -165,23 +165,23 @@ public abstract class Installer { return intent; } - void sendBroadcastInstall(Uri downloadUri, String action, PendingIntent pendingIntent) { - sendBroadcastInstall(context, downloadUri, action, apk, pendingIntent, null); + void sendBroadcastInstall(Uri canonicalUri, String action, PendingIntent pendingIntent) { + sendBroadcastInstall(context, canonicalUri, action, apk, pendingIntent, null); } - void sendBroadcastInstall(Uri downloadUri, String action) { - sendBroadcastInstall(context, downloadUri, action, apk, null, null); + void sendBroadcastInstall(Uri canonicalUri, String action) { + sendBroadcastInstall(context, canonicalUri, action, apk, null, null); } - void sendBroadcastInstall(Uri downloadUri, String action, String errorMessage) { - sendBroadcastInstall(context, downloadUri, action, apk, null, errorMessage); + void sendBroadcastInstall(Uri canonicalUri, String action, String errorMessage) { + sendBroadcastInstall(context, canonicalUri, action, apk, null, errorMessage); } static void sendBroadcastInstall(Context context, - Uri downloadUri, String action, Apk apk, + Uri canonicalUri, String action, Apk apk, PendingIntent pendingIntent, String errorMessage) { Intent intent = new Intent(action); - intent.setData(downloadUri); + intent.setData(canonicalUri); intent.putExtra(Installer.EXTRA_USER_INTERACTION_PI, pendingIntent); intent.putExtra(Installer.EXTRA_APK, apk); if (!TextUtils.isEmpty(errorMessage)) { @@ -226,20 +226,34 @@ public abstract class Installer { /** * Gets an {@link IntentFilter} for matching events from the install - * process based on the original download URL as a {@link Uri}. + * process based on {@code canonicalUri}, which is the global unique + * ID for a package going through the install process. + * + * @see InstallManagerService for more about {@code canonicalUri} */ - public static IntentFilter getInstallIntentFilter(Uri uri) { + public static IntentFilter getInstallIntentFilter(Uri canonicalUri) { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Installer.ACTION_INSTALL_STARTED); intentFilter.addAction(Installer.ACTION_INSTALL_COMPLETE); intentFilter.addAction(Installer.ACTION_INSTALL_INTERRUPTED); intentFilter.addAction(Installer.ACTION_INSTALL_USER_INTERACTION); - intentFilter.addDataScheme(uri.getScheme()); - intentFilter.addDataAuthority(uri.getHost(), String.valueOf(uri.getPort())); - intentFilter.addDataPath(uri.getPath(), PatternMatcher.PATTERN_LITERAL); + intentFilter.addDataScheme(canonicalUri.getScheme()); + intentFilter.addDataAuthority(canonicalUri.getHost(), String.valueOf(canonicalUri.getPort())); + intentFilter.addDataPath(canonicalUri.getPath(), PatternMatcher.PATTERN_LITERAL); return intentFilter; } + /** + * Gets an {@link IntentFilter} for matching events from the install + * process based on {@code canonicalUrl}, which is the global unique + * ID for a package going through the install process. + * + * @see InstallManagerService for more about {@code canonicalUrl} + */ + public static IntentFilter getInstallIntentFilter(String canonicalUrl) { + return getInstallIntentFilter(Uri.parse(canonicalUrl)); + } + public static IntentFilter getUninstallIntentFilter(String packageName) { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Installer.ACTION_UNINSTALL_STARTED); @@ -262,20 +276,20 @@ public abstract class Installer { * is prompted with the system installer dialog, which shows all the * permissions that the APK is requesting. * - * @param localApkUri points to the local copy of the APK to be installed - * @param downloadUri serves as the unique ID for all actions related to the - * installation of that specific APK + * @param localApkUri points to the local copy of the APK to be installed + * @param canonicalUri serves as the unique ID for all actions related to the + * installation of that specific APK * @see InstallManagerService * @see ACTION_INSTALL_PACKAGE Fails For Any Possible Uri */ - public void installPackage(Uri localApkUri, Uri downloadUri) { + public void installPackage(Uri localApkUri, Uri canonicalUri) { Uri sanitizedUri; try { sanitizedUri = ApkFileProvider.getSafeUri(context, localApkUri, apk); } catch (IOException e) { Utils.debugLog(TAG, e.getMessage(), e); - sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED, e.getMessage()); + sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED, e.getMessage()); return; } @@ -285,7 +299,7 @@ public abstract class Installer { apkVerifier.verifyApk(); } catch (ApkVerifier.ApkVerificationException e) { Utils.debugLog(TAG, e.getMessage(), e); - sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED, e.getMessage()); + sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED, e.getMessage()); return; } catch (ApkVerifier.ApkPermissionUnequalException e) { // if permissions of apk are not the ones listed in the repo @@ -295,15 +309,15 @@ public abstract class Installer { Utils.debugLog(TAG, e.getMessage(), e); Utils.debugLog(TAG, "Falling back to AOSP DefaultInstaller!"); DefaultInstaller defaultInstaller = new DefaultInstaller(context, apk); - defaultInstaller.installPackageInternal(sanitizedUri, downloadUri); + defaultInstaller.installPackageInternal(sanitizedUri, canonicalUri); return; } } - installPackageInternal(sanitizedUri, downloadUri); + installPackageInternal(sanitizedUri, canonicalUri); } - protected abstract void installPackageInternal(Uri localApkUri, Uri downloadUri); + protected abstract void installPackageInternal(Uri localApkUri, Uri canonicalUri); /** * Uninstall app as defined by {@link Installer#apk} in diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java index 496d46d5d..75f8f8a96 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java @@ -28,10 +28,10 @@ import android.support.annotation.NonNull; import android.support.v4.app.JobIntentService; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.WildcardFileFilter; -import org.fdroid.fdroid.views.AppDetailsActivity; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.App; +import org.fdroid.fdroid.views.AppDetailsActivity; import java.io.File; import java.io.FileFilter; @@ -74,8 +74,8 @@ public class InstallerService extends JobIntentService { if (ACTION_INSTALL.equals(intent.getAction())) { Uri uri = intent.getData(); - Uri downloadUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); - installer.installPackage(uri, downloadUri); + Uri canonicalUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); + installer.installPackage(uri, canonicalUri); } else if (ACTION_UNINSTALL.equals(intent.getAction())) { installer.uninstallPackage(); new Thread() { @@ -111,19 +111,20 @@ public class InstallerService extends JobIntentService { * {@link #uninstall(Context, Apk)} since this is called in one place where * the input has already been validated. * - * @param context this app's {@link Context} - * @param localApkUri {@link Uri} pointing to (downloaded) local apk file - * @param downloadUri {@link Uri} where the apk has been downloaded from - * @param apk apk object of app that should be installed + * @param context this app's {@link Context} + * @param localApkUri {@link Uri} pointing to (downloaded) local apk file + * @param canonicalUri {@link Uri} used as the global unique ID for the package + * @param apk apk object of app that should be installed * @see #uninstall(Context, Apk) + * @see InstallManagerService */ - public static void install(Context context, Uri localApkUri, Uri downloadUri, Apk apk) { - Installer.sendBroadcastInstall(context, downloadUri, Installer.ACTION_INSTALL_STARTED, apk, + public static void install(Context context, Uri localApkUri, Uri canonicalUri, Apk apk) { + Installer.sendBroadcastInstall(context, canonicalUri, Installer.ACTION_INSTALL_STARTED, apk, null, null); Intent intent = new Intent(context, InstallerService.class); intent.setAction(ACTION_INSTALL); intent.setData(localApkUri); - intent.putExtra(Installer.EXTRA_DOWNLOAD_URI, downloadUri); + intent.putExtra(Installer.EXTRA_DOWNLOAD_URI, canonicalUri); intent.putExtra(Installer.EXTRA_APK, apk); enqueueWork(context, intent); } diff --git a/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java index a4908e156..51e5ee8f4 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/PrivilegedInstaller.java @@ -308,7 +308,7 @@ public class PrivilegedInstaller extends Installer { } @Override - protected void installPackageInternal(final Uri localApkUri, final Uri downloadUri) { + protected void installPackageInternal(final Uri localApkUri, final Uri canonicalUri) { ServiceConnection mServiceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { IPrivilegedService privService = IPrivilegedService.Stub.asInterface(service); @@ -317,9 +317,9 @@ public class PrivilegedInstaller extends Installer { @Override public void handleResult(String packageName, int returnCode) throws RemoteException { if (returnCode == INSTALL_SUCCEEDED) { - sendBroadcastInstall(downloadUri, ACTION_INSTALL_COMPLETE); + sendBroadcastInstall(canonicalUri, ACTION_INSTALL_COMPLETE); } else { - sendBroadcastInstall(downloadUri, ACTION_INSTALL_INTERRUPTED, + sendBroadcastInstall(canonicalUri, ACTION_INSTALL_INTERRUPTED, "Error " + returnCode + ": " + INSTALL_RETURN_CODES.get(returnCode)); } @@ -329,7 +329,7 @@ public class PrivilegedInstaller extends Installer { try { boolean hasPermissions = privService.hasPrivilegedPermissions(); if (!hasPermissions) { - sendBroadcastInstall(downloadUri, ACTION_INSTALL_INTERRUPTED, + sendBroadcastInstall(canonicalUri, ACTION_INSTALL_INTERRUPTED, context.getString(R.string.system_install_denied_permissions)); return; } @@ -338,7 +338,7 @@ public class PrivilegedInstaller extends Installer { null, callback); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); - sendBroadcastInstall(downloadUri, ACTION_INSTALL_INTERRUPTED, + sendBroadcastInstall(canonicalUri, ACTION_INSTALL_INTERRUPTED, "connecting to privileged service failed"); } } diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index b4201e486..96724a76f 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -75,17 +75,18 @@ import java.net.UnknownHostException; * long as necessary (and will not block the application's main loop), but * only one request will be processed at a time. *

- * The full URL for the file to download is also used as the unique ID to + * The Canonical URL for the file to download is also used as the unique ID to * represent the download itself throughout F-Droid. This follows the model * of {@link Intent#setData(Uri)}, where the core data of an {@code Intent} is * a {@code Uri}. For places that need an {@code int} ID, * {@link String#hashCode()} should be used to get a reproducible, unique {@code int} - * from any {@code urlString}. The full URL is guaranteed to be unique since + * from any {@code canonicalUrl}. That full URL is guaranteed to be unique since * it points to a file on a filesystem. This is more important with media files * than with APKs since there is not reliable standard for a unique ID for * media files, unlike APKs with {@code packageName} and {@code versionCode}. * * @see android.app.IntentService + * @see org.fdroid.fdroid.installer.InstallManagerService */ public class DownloaderService extends Service { private static final String TAG = "DownloaderService"; @@ -332,18 +333,18 @@ public class DownloaderService extends Service { *

* All notifications are sent as an {@link Intent} via local broadcasts to be received by * - * @param context this app's {@link Context} - * @param urlString The URL to remove from the download queue + * @param context this app's {@link Context} + * @param canonicalUrl The URL to remove from the download queue * @see #queue(Context, String, long, String) */ - public static void cancel(Context context, String urlString) { - if (TextUtils.isEmpty(urlString)) { + public static void cancel(Context context, String canonicalUrl) { + if (TextUtils.isEmpty(canonicalUrl)) { return; } - Utils.debugLog(TAG, "Preparing cancellation of " + urlString + " download"); + Utils.debugLog(TAG, "Preparing cancellation of " + canonicalUrl + " download"); Intent intent = new Intent(context, DownloaderService.class); intent.setAction(ACTION_CANCEL); - intent.setData(Uri.parse(urlString)); + intent.setData(Uri.parse(canonicalUrl)); context.startService(intent); } @@ -352,21 +353,21 @@ public class DownloaderService extends Service { * This is useful for checking whether to re-register {@link android.content.BroadcastReceiver}s * in {@link android.app.Activity#onResume()}. */ - public static boolean isQueuedOrActive(String urlString) { - if (TextUtils.isEmpty(urlString)) { //NOPMD - suggests unreadable format + public static boolean isQueuedOrActive(String canonicalUrl) { + if (TextUtils.isEmpty(canonicalUrl)) { //NOPMD - suggests unreadable format return false; } if (serviceHandler == null) { return false; // this service is not even running } - return serviceHandler.hasMessages(urlString.hashCode()) || isActive(urlString); + return serviceHandler.hasMessages(canonicalUrl.hashCode()) || isActive(canonicalUrl); } /** * Check if a URL is actively being downloaded. */ - private static boolean isActive(String urlString) { - return downloader != null && TextUtils.equals(urlString, downloader.urlString); + private static boolean isActive(String downloadUrl) { + return downloader != null && TextUtils.equals(downloadUrl, downloader.urlString); } public static void setTimeout(int ms) { diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java index ec554956a..77160ceb8 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java @@ -449,7 +449,7 @@ public class AppDetailsActivity extends AppCompatActivity if (justReceived) { adapter.setIndeterminateProgress(R.string.installing); localBroadcastManager.registerReceiver(installReceiver, - Installer.getInstallIntentFilter(Uri.parse(newStatus.getCanonicalUrl()))); + Installer.getInstallIntentFilter(newStatus.getCanonicalUrl())); } break; diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index fde7af64e..7801ff82e 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -483,8 +483,8 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { } if (currentStatus != null && currentStatus.status == AppUpdateStatusManager.Status.ReadyToInstall) { - String urlString = currentStatus.apk.getCanonicalUrl(); - File apkFilePath = ApkCache.getApkDownloadPath(activity, urlString); + String canonicalUrl = currentStatus.apk.getCanonicalUrl(); + File apkFilePath = ApkCache.getApkDownloadPath(activity, canonicalUrl); Utils.debugLog(TAG, "skip download, we have already downloaded " + currentStatus.apk.getCanonicalUrl() + " to " + apkFilePath); @@ -505,10 +505,10 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { } }; - Uri apkDownloadUri = Uri.parse(urlString); - broadcastManager.registerReceiver(receiver, Installer.getInstallIntentFilter(apkDownloadUri)); + Uri canonicalUri = Uri.parse(canonicalUrl); + broadcastManager.registerReceiver(receiver, Installer.getInstallIntentFilter(canonicalUri)); Installer installer = InstallerFactory.create(activity, currentStatus.apk); - installer.installPackage(Uri.parse(apkFilePath.toURI().toString()), apkDownloadUri); + installer.installPackage(Uri.parse(apkFilePath.toURI().toString()), canonicalUri); } else { final Apk suggestedApk = ApkProvider.Helper.findSuggestedApk(activity, app); InstallManagerService.queue(activity, app, suggestedApk); diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java index a4d89fa7f..0d1ac37dd 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/items/KnownVulnAppListItemController.java @@ -5,12 +5,10 @@ import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.net.Uri; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; import android.view.View; - import org.fdroid.fdroid.AppUpdateStatusManager; import org.fdroid.fdroid.R; import org.fdroid.fdroid.data.Apk; @@ -73,8 +71,8 @@ public class KnownVulnAppListItemController extends AppListItemController { Apk suggestedApk = ApkProvider.Helper.findSuggestedApk(activity, app); if (shouldUpgradeInsteadOfUninstall(app, suggestedApk)) { LocalBroadcastManager manager = LocalBroadcastManager.getInstance(activity); - Uri uri = Uri.parse(suggestedApk.getCanonicalUrl()); - manager.registerReceiver(installReceiver, Installer.getInstallIntentFilter(uri)); + manager.registerReceiver(installReceiver, + Installer.getInstallIntentFilter(suggestedApk.getCanonicalUrl())); InstallManagerService.queue(activity, app, suggestedApk); } else { LocalBroadcastManager manager = LocalBroadcastManager.getInstance(activity); @@ -141,7 +139,8 @@ public class KnownVulnAppListItemController extends AppListItemController { try { uninstallPendingIntent.send(); - } catch (PendingIntent.CanceledException ignored) { } + } catch (PendingIntent.CanceledException ignored) { + } break; } } From 0aab6bc422bf294af0d6c6f96680c948c0091dd0 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 27 Mar 2019 13:37:21 +0100 Subject: [PATCH 11/14] standardize on EXTRA_CANONICAL_URL throughout the code base There were a few different constants used, this unifies them all into one, so that it is easy to track where it is used, and what it means. --- .../fdroid/fdroid/AppUpdateStatusManager.java | 8 +++----- .../fdroid/NotificationBroadcastReceiver.java | 2 +- .../org/fdroid/fdroid/NotificationHelper.java | 17 +++++------------ .../fdroid/installer/DefaultInstaller.java | 2 +- .../installer/DefaultInstallerActivity.java | 2 +- .../fdroid/fdroid/installer/FileInstaller.java | 3 +-- .../fdroid/installer/FileInstallerActivity.java | 2 +- .../fdroid/installer/InstallManagerService.java | 1 + .../org/fdroid/fdroid/installer/Installer.java | 9 --------- .../fdroid/installer/InstallerService.java | 4 ++-- .../java/org/fdroid/fdroid/net/Downloader.java | 9 ++++++++- .../fdroid/fdroid/views/main/MainActivity.java | 3 ++- 12 files changed, 26 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java index 6db802467..4db8c3ca2 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java +++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java @@ -72,9 +72,7 @@ public final class AppUpdateStatusManager { */ public static final String BROADCAST_APPSTATUS_REMOVED = "org.fdroid.fdroid.installer.appstatus.appchange.remove"; - public static final String EXTRA_APK_URL = "urlstring"; public static final String EXTRA_STATUS = "status"; - public static final String EXTRA_REASON_FOR_CHANGE = "reason"; public static final String REASON_READY_TO_INSTALL = "readytoinstall"; @@ -291,7 +289,7 @@ public final class AppUpdateStatusManager { private void notifyAdd(AppUpdateStatus entry) { if (!isBatchUpdating) { Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_ADDED); - broadcastIntent.putExtra(EXTRA_APK_URL, entry.getCanonicalUrl()); + broadcastIntent.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); localBroadcastManager.sendBroadcast(broadcastIntent); } @@ -300,7 +298,7 @@ public final class AppUpdateStatusManager { private void notifyChange(AppUpdateStatus entry, boolean isStatusUpdate) { if (!isBatchUpdating) { Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_CHANGED); - broadcastIntent.putExtra(EXTRA_APK_URL, entry.getCanonicalUrl()); + broadcastIntent.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); broadcastIntent.putExtra(EXTRA_IS_STATUS_UPDATE, isStatusUpdate); localBroadcastManager.sendBroadcast(broadcastIntent); @@ -310,7 +308,7 @@ public final class AppUpdateStatusManager { private void notifyRemove(AppUpdateStatus entry) { if (!isBatchUpdating) { Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_REMOVED); - broadcastIntent.putExtra(EXTRA_APK_URL, entry.getCanonicalUrl()); + broadcastIntent.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); localBroadcastManager.sendBroadcast(broadcastIntent); } diff --git a/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java b/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java index a93982cf5..5f041ae57 100644 --- a/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java +++ b/app/src/main/java/org/fdroid/fdroid/NotificationBroadcastReceiver.java @@ -14,7 +14,7 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context); - String canonicalUrl = intent.getStringExtra(NotificationHelper.EXTRA_NOTIFICATION_KEY); + String canonicalUrl = intent.getStringExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL); switch (intent.getAction()) { case NotificationHelper.BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED: manager.clearAllUpdates(); diff --git a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java index 4841b9c7f..d9c1c7377 100644 --- a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java @@ -46,13 +46,6 @@ class NotificationHelper { private static final int MAX_UPDATES_TO_SHOW = 5; private static final int MAX_INSTALLED_TO_SHOW = 10; - /** - * Unique ID used to represent this specific package's install process, - * including {@link Notification}s, also known as {@code urlString}. - * - * @see org.fdroid.fdroid.installer.InstallManagerService - */ - static final String EXTRA_NOTIFICATION_KEY = "key"; private static final String GROUP_UPDATES = "updates"; private static final String GROUP_INSTALLED = "installed"; @@ -93,14 +86,14 @@ class NotificationHelper { case AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED: updateStatusLists(); createSummaryNotifications(); - url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL); + url = intent.getStringExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL); entry = appUpdateStatusManager.get(url); if (entry != null) { createNotification(entry); } break; case AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED: - url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL); + url = intent.getStringExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL); entry = appUpdateStatusManager.get(url); updateStatusLists(); if (entry != null) { @@ -111,7 +104,7 @@ class NotificationHelper { } break; case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED: - url = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL); + url = intent.getStringExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL); notificationManager.cancel(url, NOTIFY_ID_INSTALLED); notificationManager.cancel(url, NOTIFY_ID_UPDATES); updateStatusLists(); @@ -346,7 +339,7 @@ class NotificationHelper { } Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED); - intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getCanonicalUrl()); + intentDeleted.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); intentDeleted.setClass(context, NotificationBroadcastReceiver.class); PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT); builder.setDeleteIntent(piDeleted); @@ -435,7 +428,7 @@ class NotificationHelper { } Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED); - intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getCanonicalUrl()); + intentDeleted.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); intentDeleted.setClass(context, NotificationBroadcastReceiver.class); PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT); builder.setDeleteIntent(piDeleted); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java index af3535ba5..9a164e703 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstaller.java @@ -47,7 +47,7 @@ public class DefaultInstaller extends Installer { Intent installIntent = new Intent(context, DefaultInstallerActivity.class); installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE); - installIntent.putExtra(Installer.EXTRA_DOWNLOAD_URI, canonicalUri); + installIntent.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, canonicalUri); installIntent.putExtra(Installer.EXTRA_APK, apk); installIntent.setData(localApkUri); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java index a0e32e6c9..60367f4bb 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java @@ -66,7 +66,7 @@ public class DefaultInstallerActivity extends FragmentActivity { installer = new DefaultInstaller(this, apk); if (ACTION_INSTALL_PACKAGE.equals(action)) { Uri localApkUri = intent.getData(); - canonicalUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); + canonicalUri = intent.getParcelableExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL); installPackage(localApkUri); } else if (ACTION_UNINSTALL_PACKAGE.equals(action)) { uninstallPackage(apk.packageName); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java b/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java index 63975208a..7a2f5cd41 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/FileInstaller.java @@ -23,7 +23,6 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.net.Uri; - import android.support.annotation.NonNull; import org.fdroid.fdroid.data.Apk; @@ -52,7 +51,7 @@ public class FileInstaller extends Installer { protected void installPackageInternal(Uri localApkUri, Uri canonicalUri) { Intent installIntent = new Intent(context, FileInstallerActivity.class); installIntent.setAction(FileInstallerActivity.ACTION_INSTALL_FILE); - installIntent.putExtra(Installer.EXTRA_DOWNLOAD_URI, canonicalUri); + installIntent.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, canonicalUri); installIntent.putExtra(Installer.EXTRA_APK, apk); installIntent.setData(localApkUri); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java b/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java index 5d7d1ddb3..42a4cdbd6 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/FileInstallerActivity.java @@ -53,7 +53,7 @@ public class FileInstallerActivity extends FragmentActivity { Intent intent = getIntent(); String action = intent.getAction(); localApkUri = intent.getData(); - canonicalUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); + canonicalUri = intent.getParcelableExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL); apk = intent.getParcelableExtra(Installer.EXTRA_APK); installer = new FileInstaller(this, apk); if (ACTION_INSTALL_FILE.equals(action)) { 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 78fae9b1c..b1ab3a643 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -68,6 +68,7 @@ import java.io.IOException; *

  • for a {@code String} ID, use {@code canonicalUrl}, {@link Uri#toString()}, or * {@link Intent#getDataString()} *
  • for an {@code int} ID, use {@link String#hashCode()} or {@link Uri#hashCode()} + *
  • for an {@link Intent} extra, use {@link org.fdroid.fdroid.net.Downloader#EXTRA_CANONICAL_URL} *

    * The implementations of {@link Uri#toString()} and {@link Intent#getDataString()} both * include caching of the generated {@code String}, so it should be plenty fast. diff --git a/app/src/main/java/org/fdroid/fdroid/installer/Installer.java b/app/src/main/java/org/fdroid/fdroid/installer/Installer.java index 9b646a988..7c3e7e761 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/Installer.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/Installer.java @@ -64,15 +64,6 @@ public abstract class Installer { public static final String ACTION_UNINSTALL_INTERRUPTED = "org.fdroid.fdroid.installer.Installer.action.UNINSTALL_INTERRUPTED"; public static final String ACTION_UNINSTALL_USER_INTERACTION = "org.fdroid.fdroid.installer.Installer.action.UNINSTALL_USER_INTERACTION"; - /** - * The URI where the APK was originally downloaded from. This is also used - * as the unique ID representing this in the whole install process in - * {@link InstallManagerService}, there is is generally known as the - * "download URL" since it is the URL used to download the APK. - * - * @see Intent#EXTRA_ORIGINATING_URI - */ - static final String EXTRA_DOWNLOAD_URI = "org.fdroid.fdroid.installer.Installer.extra.DOWNLOAD_URI"; public static final String EXTRA_APK = "org.fdroid.fdroid.installer.Installer.extra.APK"; public static final String EXTRA_USER_INTERACTION_PI = "org.fdroid.fdroid.installer.Installer.extra.USER_INTERACTION_PI"; public static final String EXTRA_ERROR_MESSAGE = "org.fdroid.fdroid.net.installer.Installer.extra.ERROR_MESSAGE"; diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java index 75f8f8a96..ac927d392 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java @@ -74,7 +74,7 @@ public class InstallerService extends JobIntentService { if (ACTION_INSTALL.equals(intent.getAction())) { Uri uri = intent.getData(); - Uri canonicalUri = intent.getParcelableExtra(Installer.EXTRA_DOWNLOAD_URI); + Uri canonicalUri = intent.getParcelableExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL); installer.installPackage(uri, canonicalUri); } else if (ACTION_UNINSTALL.equals(intent.getAction())) { installer.uninstallPackage(); @@ -124,7 +124,7 @@ public class InstallerService extends JobIntentService { Intent intent = new Intent(context, InstallerService.class); intent.setAction(ACTION_INSTALL); intent.setData(localApkUri); - intent.putExtra(Installer.EXTRA_DOWNLOAD_URI, canonicalUri); + intent.putExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL, canonicalUri); intent.putExtra(Installer.EXTRA_APK, apk); enqueueWork(context, intent); } diff --git a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java index f37a6dcd6..7acde08c6 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java +++ b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java @@ -30,8 +30,15 @@ public abstract class Downloader { public static final String EXTRA_TOTAL_BYTES = "org.fdroid.fdroid.net.Downloader.extra.TOTAL_BYTES"; public static final String EXTRA_ERROR_MESSAGE = "org.fdroid.fdroid.net.Downloader.extra.ERROR_MESSAGE"; public static final String EXTRA_REPO_ID = "org.fdroid.fdroid.net.Downloader.extra.REPO_ID"; - public static final String EXTRA_CANONICAL_URL = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL"; public static final String EXTRA_MIRROR_URL = "org.fdroid.fdroid.net.Downloader.extra.MIRROR_URL"; + /** + * Unique ID used to represent this specific package's install process, + * including {@link android.app.Notification}s, also known as {@code canonicalUrl}. + * + * @see org.fdroid.fdroid.installer.InstallManagerService + * @see android.content.Intent#EXTRA_ORIGINATING_URI + */ + public static final String EXTRA_CANONICAL_URL = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL"; public static final int DEFAULT_TIMEOUT = 10000; public static final int SECOND_TIMEOUT = (int) DateUtils.MINUTE_IN_MILLIS; diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index d108c85e4..4022b3c79 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -479,7 +479,8 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB } // Check if we have moved into the ReadyToInstall or Installed state. - AppUpdateStatus status = manager.get(intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL)); + AppUpdateStatus status = manager.get( + intent.getStringExtra(org.fdroid.fdroid.net.Downloader.EXTRA_CANONICAL_URL)); boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false); if (isStatusChange && status != null From edb2b838ebbfaab169c2bec19c9f6493b247fb7d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 10:08:01 +0100 Subject: [PATCH 12/14] DownloaderService: track active using the canonical URL This was using the actual download URL, which might change, depending on whether a mirror was used. closes #1727 --- .../fdroid/fdroid/net/DownloaderService.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index 96724a76f..56759149a 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -97,6 +97,7 @@ public class DownloaderService extends Service { private volatile Looper serviceLooper; private static volatile ServiceHandler serviceHandler; private static volatile Downloader downloader; + private static volatile String activeCanonicalUrl; private LocalBroadcastManager localBroadcastManager; private static volatile int timeout; @@ -139,16 +140,21 @@ public class DownloaderService extends Service { Utils.debugLog(TAG, "Received Intent with no URI: " + intent); return START_NOT_STICKY; } + String canonicalUrl = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); + if (canonicalUrl == null) { + Utils.debugLog(TAG, "Received Intent with no EXTRA_CANONICAL_URL: " + intent); + return START_NOT_STICKY; + } if (ACTION_CANCEL.equals(intent.getAction())) { Utils.debugLog(TAG, "Cancelling download of " + uriString); - Integer whatToRemove = uriString.hashCode(); + Integer whatToRemove = canonicalUrl.hashCode(); if (serviceHandler.hasMessages(whatToRemove)) { Utils.debugLog(TAG, "Removing download with ID of " + whatToRemove + " from service handler, then sending interrupted event."); serviceHandler.removeMessages(whatToRemove); - sendBroadcast(intent.getData(), Downloader.ACTION_INTERRUPTED); - } else if (isActive(uriString)) { + sendCancelledBroadcast(intent.getData(), canonicalUrl); + } else if (isActive(canonicalUrl)) { downloader.cancelDownload(); } else { Utils.debugLog(TAG, "ACTION_CANCEL called on something not queued or running" @@ -158,7 +164,7 @@ public class DownloaderService extends Service { Message msg = serviceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; - msg.what = uriString.hashCode(); + msg.what = canonicalUrl.hashCode(); serviceHandler.sendMessage(msg); Utils.debugLog(TAG, "Queued download of " + uriString); } else { @@ -207,6 +213,7 @@ public class DownloaderService extends Service { sendBroadcast(uri, Downloader.ACTION_STARTED, localFile, repoId, canonicalUrl); try { + activeCanonicalUrl = canonicalUrl.toString(); downloader = DownloaderFactory.create(this, uri, localFile); downloader.setListener(new ProgressListener() { @Override @@ -244,20 +251,17 @@ public class DownloaderService extends Service { } } downloader = null; + activeCanonicalUrl = null; } - private void sendBroadcast(Uri uri, String action) { - sendBroadcast(uri, action, null, null); + private void sendCancelledBroadcast(Uri uri, String canonicalUrl) { + sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, null, 0, Uri.parse(canonicalUrl)); } private void sendBroadcast(Uri uri, String action, File file, long repoId, Uri canonicalUrl) { sendBroadcast(uri, action, file, null, repoId, canonicalUrl); } - private void sendBroadcast(Uri uri, String action, File file, String errorMessage) { - sendBroadcast(uri, action, file, errorMessage, 0, null); - } - private void sendBroadcast(Uri uri, String action, File file, String errorMessage, long repoId, Uri canonicalUrl) { Intent intent = new Intent(action); @@ -345,6 +349,7 @@ public class DownloaderService extends Service { Intent intent = new Intent(context, DownloaderService.class); intent.setAction(ACTION_CANCEL); intent.setData(Uri.parse(canonicalUrl)); + intent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUrl); context.startService(intent); } @@ -367,7 +372,7 @@ public class DownloaderService extends Service { * Check if a URL is actively being downloaded. */ private static boolean isActive(String downloadUrl) { - return downloader != null && TextUtils.equals(downloadUrl, downloader.urlString); + return downloader != null && TextUtils.equals(downloadUrl, activeCanonicalUrl); } public static void setTimeout(int ms) { From 5f14628524ade8db28d383dc4c015df2a6dcc1e4 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 10:10:33 +0100 Subject: [PATCH 13/14] DownloaderService: improve debug logs for Canonical vs Download URLs --- .../installer/InstallManagerService.java | 1 + .../fdroid/fdroid/net/DownloaderService.java | 22 ++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) 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 b1ab3a643..24d86fa36 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -159,6 +159,7 @@ public class InstallManagerService extends Service { DownloaderService.cancel(this, canonicalUrl); Apk apk = appUpdateStatusManager.getApk(canonicalUrl); if (apk != null) { + Utils.debugLog(TAG, "also canceling OBB downloads"); DownloaderService.cancel(this, apk.getPatchObbUrl()); DownloaderService.cancel(this, apk.getMainObbUrl()); } diff --git a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java index 56759149a..cca7e76ee 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -32,6 +32,8 @@ import android.os.Process; import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.util.Log; +import android.util.LogPrinter; +import org.fdroid.fdroid.BuildConfig; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.ProgressListener; import org.fdroid.fdroid.R; @@ -102,6 +104,8 @@ public class DownloaderService extends Service { private static volatile int timeout; private final class ServiceHandler extends Handler { + static final String TAG = "ServiceHandler"; + ServiceHandler(Looper looper) { super(looper); } @@ -123,6 +127,9 @@ public class DownloaderService extends Service { thread.start(); serviceLooper = thread.getLooper(); + if (BuildConfig.DEBUG) { + serviceLooper.setMessageLogging(new LogPrinter(Log.DEBUG, ServiceHandler.TAG)); + } serviceHandler = new ServiceHandler(serviceLooper); localBroadcastManager = LocalBroadcastManager.getInstance(this); } @@ -135,8 +142,8 @@ public class DownloaderService extends Service { return START_NOT_STICKY; } - String uriString = intent.getDataString(); - if (uriString == null) { + String downloadUrl = intent.getDataString(); + if (downloadUrl == null) { Utils.debugLog(TAG, "Received Intent with no URI: " + intent); return START_NOT_STICKY; } @@ -147,7 +154,8 @@ public class DownloaderService extends Service { } if (ACTION_CANCEL.equals(intent.getAction())) { - Utils.debugLog(TAG, "Cancelling download of " + uriString); + Utils.debugLog(TAG, "Cancelling download of " + canonicalUrl.hashCode() + "/" + canonicalUrl + + " downloading from " + downloadUrl); Integer whatToRemove = canonicalUrl.hashCode(); if (serviceHandler.hasMessages(whatToRemove)) { Utils.debugLog(TAG, "Removing download with ID of " + whatToRemove @@ -166,7 +174,8 @@ public class DownloaderService extends Service { msg.obj = intent; msg.what = canonicalUrl.hashCode(); serviceHandler.sendMessage(msg); - Utils.debugLog(TAG, "Queued download of " + uriString); + Utils.debugLog(TAG, "Queued download of " + canonicalUrl.hashCode() + "/" + canonicalUrl + + " using " + downloadUrl); } else { Utils.debugLog(TAG, "Received Intent with unknown action: " + intent); } @@ -294,7 +303,8 @@ public class DownloaderService extends Service { if (TextUtils.isEmpty(mirrorUrl)) { return; } - Utils.debugLog(TAG, "Preparing " + mirrorUrl + " to go into the download queue"); + Utils.debugLog(TAG, "Queue download " + canonicalUrl.hashCode() + "/" + canonicalUrl + + " using " + mirrorUrl); Intent intent = new Intent(context, DownloaderService.class); intent.setAction(ACTION_QUEUE); intent.setData(Uri.parse(mirrorUrl)); @@ -345,7 +355,7 @@ public class DownloaderService extends Service { if (TextUtils.isEmpty(canonicalUrl)) { return; } - Utils.debugLog(TAG, "Preparing cancellation of " + canonicalUrl + " download"); + Utils.debugLog(TAG, "Send cancel for " + canonicalUrl.hashCode() + "/" + canonicalUrl); Intent intent = new Intent(context, DownloaderService.class); intent.setAction(ACTION_CANCEL); intent.setData(Uri.parse(canonicalUrl)); From c7c16131e94ac950f7c100e8fea542c719e28a92 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 10:45:56 +0100 Subject: [PATCH 14/14] fix OBB support for repositories The repoId was hard-coded to 0. fdroid/fdroidclient#1403 --- .../installer/InstallManagerService.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) 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 24d86fa36..03b863010 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -207,8 +207,8 @@ public class InstallManagerService extends Service { appUpdateStatusManager.addApk(apk, AppUpdateStatusManager.Status.Downloading, null); registerPackageDownloaderReceivers(canonicalUrl); - getObb(canonicalUrl, apk.getMainObbUrl(), apk.getMainObbFile(), apk.obbMainFileSha256); - getObb(canonicalUrl, apk.getPatchObbUrl(), apk.getPatchObbFile(), apk.obbPatchFileSha256); + getMainObb(canonicalUrl, apk); + getPatchObb(canonicalUrl, apk); File apkFilePath = ApkCache.getApkDownloadPath(this, apk.getCanonicalUrl()); long apkFileSize = apkFilePath.length(); @@ -235,6 +235,14 @@ public class InstallManagerService extends Service { localBroadcastManager.sendBroadcast(intent); } + private void getMainObb(final String canonicalUrl, Apk apk) { + getObb(canonicalUrl, apk.getMainObbUrl(), apk.getMainObbFile(), apk.obbMainFileSha256, apk.repoId); + } + + private void getPatchObb(final String canonicalUrl, Apk apk) { + getObb(canonicalUrl, apk.getPatchObbUrl(), apk.getPatchObbFile(), apk.obbPatchFileSha256, apk.repoId); + } + /** * Check if any OBB files are available, and if so, download and install them. This * also deletes any obsolete OBB files, per the spec, since there can be only one @@ -243,7 +251,7 @@ public class InstallManagerService extends Service { * @see APK Expansion Files */ private void getObb(final String canonicalUrl, String obbUrlString, - final File obbDestFile, final String hash) { + final File obbDestFile, final String hash, final long repoId) { if (obbDestFile == null || obbDestFile.exists() || TextUtils.isEmpty(obbUrlString)) { return; } @@ -293,13 +301,13 @@ public class InstallManagerService extends Service { } else if (Downloader.ACTION_INTERRUPTED.equals(action)) { localBroadcastManager.unregisterReceiver(this); } else if (Downloader.ACTION_CONNECTION_FAILED.equals(action)) { - DownloaderService.queueUsingDifferentMirror(context, 0, canonicalUrl); + DownloaderService.queueUsingDifferentMirror(context, repoId, canonicalUrl); } else { throw new RuntimeException("intent action not handled!"); } } }; - DownloaderService.queueUsingRandomMirror(this, 0, obbUrlString); + DownloaderService.queueUsingRandomMirror(this, repoId, obbUrlString); localBroadcastManager.registerReceiver(downloadReceiver, DownloaderService.getIntentFilter(obbUrlString)); }