diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index eca09c6bd..718425140 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -408,13 +408,29 @@ public final class Utils { byte[] mdbytes = md.digest(); return toHexString(mdbytes).toLowerCase(Locale.ENGLISH); - } catch (IOException | NoSuchAlgorithmException e) { + } catch (IOException e) { + // The annoyance (potentially) caused by miscellaneous filesystem corruption results in + // F-Droid constantly popping up crash reports when F-Droid isn't even open. As such this + // exception-message-parsing-and-throwing-a-new-ignorable-exception-hackery is probably + // warranted. See https://www.gitlab.com/fdroid/fdroidclient/issues/855 for more detail. + if (e.getMessage().contains("read failed: EIO (I/O error)")) { + throw new PotentialFilesystemCorruptionException(e); + } + + throw new IllegalArgumentException(e); + } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } finally { closeQuietly(fis); } } + public static class PotentialFilesystemCorruptionException extends IllegalArgumentException { + public PotentialFilesystemCorruptionException(IOException e) { + super(e); + } + } + /** * Computes the base 16 representation of the byte array argument. * 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 6f0dee7fb..6d465e725 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -8,13 +8,19 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.net.Uri; +import android.os.Handler; +import android.os.Looper; import android.os.Process; import android.support.annotation.Nullable; - +import android.util.Log; +import android.widget.Toast; import org.acra.ACRA; import org.fdroid.fdroid.Hasher; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Schema.InstalledAppTable; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subjects.PublishSubject; import java.io.File; import java.io.FilenameFilter; @@ -23,10 +29,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import rx.functions.Action1; -import rx.schedulers.Schedulers; -import rx.subjects.PublishSubject; - /** * Handles all updates to {@link InstalledAppProvider}, whether checking the contents * versus what Android says is installed, or processing {@link Intent}s that come @@ -197,6 +199,22 @@ public class InstalledAppProviderService extends IntentService { String hashType = "sha256"; String hash = Utils.getBinaryHash(apk, hashType); insertAppIntoDb(this, packageInfo, hashType, hash); + } catch (final Utils.PotentialFilesystemCorruptionException e) { + Log.e(TAG, "Encountered potential filesystem corruption, or other unknown " + + "problem when calculating hash of " + apk.getAbsolutePath() + ". " + + "It is unlikely F-Droid can do anything about this, and this " + + "likely happened in the background. As such, we will continue without " + + "interrupting the user by asking them to send a crash report."); + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + + @Override + public void run() { + Context context = getApplicationContext(); + Toast.makeText(context, e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); + } + }); + return; } catch (IllegalArgumentException e) { Utils.debugLog(TAG, e.getMessage()); ACRA.getErrorReporter().handleException(e, false);