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 12a20b692..c6a5e2272 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -25,6 +25,7 @@ import org.fdroid.fdroid.net.Downloader; import org.fdroid.fdroid.net.DownloaderService; import java.io.File; +import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -144,7 +145,7 @@ public class InstallManagerService extends Service { if (!apkFilePath.exists() || apkFileSize < apk.size) { Utils.debugLog(TAG, "download " + urlString + " " + apkFilePath); DownloaderService.queue(this, urlString); - } else if (apkFileSize == apk.size) { + } else if (apkIsCached(apkFilePath, apk)) { Utils.debugLog(TAG, "skip download, we have it, straight to install " + urlString + " " + apkFilePath); sendBroadcast(intent.getData(), Downloader.ACTION_STARTED, apkFilePath); sendBroadcast(intent.getData(), Downloader.ACTION_COMPLETE, apkFilePath); @@ -156,6 +157,21 @@ public class InstallManagerService extends Service { return START_REDELIVER_INTENT; // if killed before completion, retry Intent } + /** + * Verifies the size of the file on disk matches, and then hashes the file to compare with what + * we received from the signed repo (i.e. {@link Apk#hash} and {@link Apk#hashType}). + * Bails out if the file sizes don't match to prevent having to do the work of hashing the file. + */ + private static boolean apkIsCached(File apkFile, Apk apkToCheck) { + try { + return apkFile.length() == apkToCheck.size && + Installer.verifyApkFile(apkFile, apkToCheck.hash, apkToCheck.hashType); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return false; + } + } + private void sendBroadcast(Uri uri, String action, File file) { Intent intent = new Intent(action); intent.setData(uri); @@ -210,9 +226,7 @@ public class InstallManagerService extends Service { Apk apk = ACTIVE_APKS.remove(urlString); ACTIVE_APPS.remove(apk.packageName); unregisterDownloaderReceivers(urlString); - if (AppDetails.isAppVisible(apk.packageName)) { - cancelNotification(urlString); - } + cancelNotification(urlString); } }; localBroadcastManager.registerReceiver(startedReceiver, @@ -245,13 +259,13 @@ public class InstallManagerService extends Service { App app = ACTIVE_APPS.get(apk.packageName); if (app == null || TextUtils.isEmpty(app.name)) { if (TEMP_HACK_APP_NAMES.containsKey(urlString)) { - return getString(R.string.downloading_apk, TEMP_HACK_APP_NAMES.get(urlString)); + return TEMP_HACK_APP_NAMES.get(urlString); } else { // this is ugly, but its better than nothing as a failsafe - return getString(R.string.downloading_apk, urlString); + return urlString; } } else { - return getString(R.string.downloading_apk, app.name); + return app.name; } } 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 41266f021..daf27221d 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/Installer.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/Installer.java @@ -156,7 +156,7 @@ public abstract class Installer { /** * Checks the APK file against the provided hash, returning whether it is a match. */ - private static boolean verifyApkFile(File apkFile, String hash, String hashType) + public static boolean verifyApkFile(File apkFile, String hash, String hashType) throws NoSuchAlgorithmException { if (!apkFile.exists()) { return false; 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 7e5961d95..a85d311ab 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/DownloaderService.java @@ -89,6 +89,7 @@ public class DownloaderService extends Service { @Override public void handleMessage(Message msg) { + Utils.debugLog(TAG, "Handling download message with ID of " + msg.what); handleIntent((Intent) msg.obj); stopSelf(msg.arg1); } @@ -120,12 +121,13 @@ public class DownloaderService extends Service { Utils.debugLog(TAG, "Cancelling download of " + uriString); Integer whatToRemove = uriString.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)) { downloader.cancelDownload(); } else { - Log.e(TAG, "ACTION_CANCEL called on something not queued or running"); + Log.e(TAG, "ACTION_CANCEL called on something not queued or running (expected to find message with ID of " + whatToRemove + " in queue)."); } } else if (ACTION_QUEUE.equals(intent.getAction())) { Message msg = serviceHandler.obtainMessage();