From 3378c0a333bb84d55aeb0c608d9b40ed32b2b0f3 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 27 Mar 2019 13:13:53 +0100 Subject: [PATCH] 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. *

@@ -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; } }