do not crash if file vanishes during getBinaryHash()

APKs can be deleted at any time, either by being uninstalled or deleted
from the cache.
This commit is contained in:
Hans-Christoph Steiner 2018-03-07 15:23:01 +01:00
parent 86cc977746
commit 6055874d9d

View File

@ -38,12 +38,10 @@ import android.text.style.TypefaceSpan;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.utils.StorageUtils; import com.nostra13.universalimageloader.utils.StorageUtils;
import org.fdroid.fdroid.compat.FileCompat; import org.fdroid.fdroid.compat.FileCompat;
import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.SanitizedFile; import org.fdroid.fdroid.data.SanitizedFile;
@ -91,7 +89,7 @@ public final class Utils {
new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss", Locale.ENGLISH); new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss", Locale.ENGLISH);
private static final String[] FRIENDLY_SIZE_FORMAT = { private static final String[] FRIENDLY_SIZE_FORMAT = {
"%.0f B", "%.0f KiB", "%.1f MiB", "%.2f GiB", "%.0f B", "%.0f KiB", "%.1f MiB", "%.2f GiB",
}; };
public static final String FALLBACK_ICONS_DIR = "/icons/"; public static final String FALLBACK_ICONS_DIR = "/icons/";
@ -205,31 +203,31 @@ public final class Utils {
} }
private static final String[] ANDROID_VERSION_NAMES = { private static final String[] ANDROID_VERSION_NAMES = {
"?", // 0, undefined "?", // 0, undefined
"1.0", // 1 "1.0", // 1
"1.1", // 2 "1.1", // 2
"1.5", // 3 "1.5", // 3
"1.6", // 4 "1.6", // 4
"2.0", // 5 "2.0", // 5
"2.0.1", // 6 "2.0.1", // 6
"2.1", // 7 "2.1", // 7
"2.2", // 8 "2.2", // 8
"2.3", // 9 "2.3", // 9
"2.3.3", // 10 "2.3.3", // 10
"3.0", // 11 "3.0", // 11
"3.1", // 12 "3.1", // 12
"3.2", // 13 "3.2", // 13
"4.0", // 14 "4.0", // 14
"4.0.3", // 15 "4.0.3", // 15
"4.1", // 16 "4.1", // 16
"4.2", // 17 "4.2", // 17
"4.3", // 18 "4.3", // 18
"4.4", // 19 "4.4", // 19
"4.4W", // 20 "4.4W", // 20
"5.0", // 21 "5.0", // 21
"5.1", // 22 "5.1", // 22
"6.0", // 23 "6.0", // 23
"7.0", // 24 "7.0", // 24
}; };
public static String getAndroidVersionName(int sdkLevel) { public static String getAndroidVersionName(int sdkLevel) {
@ -400,7 +398,16 @@ public final class Utils {
/** /**
* Get the checksum hash of the file {@code apk} using the algorithm in {@code algo}. * Get the checksum hash of the file {@code apk} using the algorithm in {@code algo}.
* {@code apk} must exist on the filesystem and {@code algo} must be supported * {@code apk} must exist on the filesystem and {@code algo} must be supported
* by this device, otherwise an {@link IllegalArgumentException} is thrown. * by this device, otherwise an {@link IllegalArgumentException} is thrown. This
* method must be very defensive about checking whether the file exists, since APKs
* can be uninstalled/deleted in background at any time, even if this is in the
* middle of running.
* <p>
* This also will run into filesystem corruption if the device is having trouble.
* So hide those so F-Droid does not pop up crash reports about that. 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.
*/ */
public static String getBinaryHash(File apk, String algo) { public static String getBinaryHash(File apk, String algo) {
FileInputStream fis = null; FileInputStream fis = null;
@ -418,14 +425,12 @@ public final class Utils {
byte[] mdbytes = md.digest(); byte[] mdbytes = md.digest();
return toHexString(mdbytes).toLowerCase(Locale.ENGLISH); return toHexString(mdbytes).toLowerCase(Locale.ENGLISH);
} catch (IOException e) { } catch (IOException e) {
// The annoyance (potentially) caused by miscellaneous filesystem corruption results in String message = e.getMessage();
// F-Droid constantly popping up crash reports when F-Droid isn't even open. As such this if (message.contains("read failed: EIO (I/O error)")) {
// 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 PotentialFilesystemCorruptionException(e);
} else if (message.contains(" ENOENT ")) {
Utils.debugLog(TAG, apk + " vanished: " + message);
} }
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
@ -537,10 +542,10 @@ public final class Utils {
public static String formatLastUpdated(@NonNull Resources res, @NonNull Date date) { public static String formatLastUpdated(@NonNull Resources res, @NonNull Date date) {
long msDiff = Calendar.getInstance().getTimeInMillis() - date.getTime(); long msDiff = Calendar.getInstance().getTimeInMillis() - date.getTime();
long days = msDiff / DateUtils.DAY_IN_MILLIS; long days = msDiff / DateUtils.DAY_IN_MILLIS;
long weeks = msDiff / (DateUtils.DAY_IN_MILLIS * 7); long weeks = msDiff / (DateUtils.DAY_IN_MILLIS * 7);
long months = msDiff / (DateUtils.DAY_IN_MILLIS * 30); long months = msDiff / (DateUtils.DAY_IN_MILLIS * 30);
long years = msDiff / (DateUtils.DAY_IN_MILLIS * 365); long years = msDiff / (DateUtils.DAY_IN_MILLIS * 365);
if (days < 1) { if (days < 1) {
return res.getString(R.string.details_last_updated_today); return res.getString(R.string.details_last_updated_today);