, Parcelable {
setRequestedPermissions(permissions, 23);
}
+ /**
+ * Generate the set of requested permissions for the current Android version.
+ *
+ * There are also a bunch of crazy rules where having one permission will imply
+ * another permission, for example, {@link Manifest.permission#WRITE_EXTERNAL_STORAGE}
+ * implies {@code Manifest.permission#READ_EXTERNAL_STORAGE}. Many of these rules
+ * are for quite old Android versions, so they are not included here.
+ *
+ * @see Manifest.permission#READ_EXTERNAL_STORAGE
+ */
private void setRequestedPermissions(Object[][] permissions, int minSdk) {
HashSet set = new HashSet<>();
if (requestedPermissions != null) {
@@ -500,6 +511,9 @@ public class Apk extends ValueObject implements Comparable, Parcelable {
set.add((String) versions[0]);
}
}
+ if (Build.VERSION.SDK_INT >= 16 && set.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ set.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ }
requestedPermissions = set.toArray(new String[set.size()]);
}
diff --git a/app/src/main/java/org/fdroid/fdroid/data/Repo.java b/app/src/main/java/org/fdroid/fdroid/data/Repo.java
index 1a9929789..43fbe65e8 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/Repo.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/Repo.java
@@ -389,6 +389,10 @@ public class Repo extends ValueObject {
* URL in the mirrors list so the mirror logic works on the first index
* update. That makes it possible to do the first index update via SD Card
* or USB OTG drive.
+ *
+ * @see FDroidApp#resetMirrorVars()
+ * @see FDroidApp#getMirror(String, Repo)
+ * @see FDroidApp#getTimeout()
*/
public String getMirror(String lastWorkingMirror) {
if (TextUtils.isEmpty(lastWorkingMirror)) {
diff --git a/app/src/main/java/org/fdroid/fdroid/data/RepoXMLHandler.java b/app/src/main/java/org/fdroid/fdroid/data/RepoXMLHandler.java
index 1da274f63..58287bdda 100644
--- a/app/src/main/java/org/fdroid/fdroid/data/RepoXMLHandler.java
+++ b/app/src/main/java/org/fdroid/fdroid/data/RepoXMLHandler.java
@@ -19,6 +19,7 @@
package org.fdroid.fdroid.data;
+import android.Manifest;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -98,6 +99,10 @@ public class RepoXMLHandler extends DefaultHandler {
if ("application".equals(localName) && curapp != null) {
onApplicationParsed();
} else if ("package".equals(localName) && curapk != null && curapp != null) {
+ if (Build.VERSION.SDK_INT >= 16 &&
+ requestedPermissionsSet.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ requestedPermissionsSet.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ }
int size = requestedPermissionsSet.size();
curapk.requestedPermissions = requestedPermissionsSet.toArray(new String[size]);
requestedPermissionsSet.clear();
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 2175344dd..7a7ebb232 100644
--- a/app/src/main/java/org/fdroid/fdroid/net/Downloader.java
+++ b/app/src/main/java/org/fdroid/fdroid/net/Downloader.java
@@ -2,7 +2,7 @@ package org.fdroid.fdroid.net;
import android.net.Uri;
import android.support.annotation.NonNull;
-
+import android.text.format.DateUtils;
import org.fdroid.fdroid.ProgressListener;
import org.fdroid.fdroid.Utils;
@@ -33,6 +33,10 @@ public abstract class Downloader {
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 int DEFAULT_TIMEOUT = 10000;
+ public static final int SECOND_TIMEOUT = (int) DateUtils.MINUTE_IN_MILLIS;
+ public static final int LONGEST_TIMEOUT = 600000; // 10 minutes
+
private volatile boolean cancelled = false;
private volatile long bytesRead;
private volatile long totalBytes;
@@ -43,7 +47,7 @@ public abstract class Downloader {
String cacheTag;
boolean notFound;
- private volatile int timeout = 10000;
+ private volatile int timeout = DEFAULT_TIMEOUT;
/**
* For sending download progress, should only be called in {@link #progressTask}
diff --git a/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java b/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java
index a6fe63dc2..62dc3a56f 100644
--- a/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java
+++ b/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java
@@ -176,6 +176,7 @@ public class HttpDownloader extends Downloader {
connection.setRequestProperty("User-Agent", "F-Droid " + BuildConfig.VERSION_NAME);
connection.setConnectTimeout(getTimeout());
+ connection.setReadTimeout(getTimeout());
if (Build.VERSION.SDK_INT < 19) { // gzip encoding can be troublesome on old Androids
connection.setRequestProperty("Accept-Encoding", "identity");
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9a7869280..4c9b9e5c4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -51,7 +51,7 @@
them
Automatically install updates
- Download and install update apps in the background
+ Download and update apps in the background, showing a notification
Show available updates
Show a notification when updates are available
Privileged Extension
diff --git a/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java b/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java
index cc9d6394d..3a8d231ef 100644
--- a/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java
+++ b/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java
@@ -38,6 +38,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -53,6 +55,7 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -132,6 +135,14 @@ public class IndexV1UpdaterTest extends FDroidProviderTest {
InstalledAppTestUtils.install(context, "com.waze", 1019841, "v3.9.5.4", "362488e7be5ea0689b4e97d989ae1404",
"cbbdb8c5dafeccd7dd7b642dde0477d3489e18ac366e3c8473d5c07e5f735a95");
assertEquals(1, AppProvider.Helper.findInstalledAppsWithKnownVulns(context).size());
+
+ Apk apk = ApkProvider.Helper.findApkFromAnyRepo(context, "io.proto.player", 1110);
+ assertNotNull("We should find this APK", apk);
+ assertEquals("io.proto.player-1.apk", apk.apkName);
+ HashSet requestedPermissions = new HashSet<>(Arrays.asList(apk.requestedPermissions));
+ assertTrue(requestedPermissions.contains(android.Manifest.permission.READ_EXTERNAL_STORAGE));
+ assertTrue(requestedPermissions.contains(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
+ assertFalse(requestedPermissions.contains(android.Manifest.permission.READ_CALENDAR));
}
@Test(expected = IndexUpdater.SigningException.class)