summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Sullins <jcsullins@gmail.com>2014-09-05 12:10:28 -0500
committerRaj <raj@cyngn.com>2014-10-29 00:15:23 -0700
commit97086b259248d3d46a0d558aff8a32d1c6987777 (patch)
treefdc2e6977497dca8a33cd18b0fafff3b653d766d
parent53804e41e6eb6963f802eaeeb1729b3adda4ca8a (diff)
downloadandroid_packages_providers_DownloadProvider-97086b259248d3d46a0d558aff8a32d1c6987777.zip
android_packages_providers_DownloadProvider-97086b259248d3d46a0d558aff8a32d1c6987777.tar.gz
android_packages_providers_DownloadProvider-97086b259248d3d46a0d558aff8a32d1c6987777.tar.bz2
DownloadProvider: fix secondary storage support
Change-Id: If9aba4c73b24d052b0379d624302ffda03fdf8e4
-rw-r--r--src/com/android/providers/downloads/DownloadProvider.java29
-rwxr-xr-xsrc/com/android/providers/downloads/DownloadThread.java5
-rw-r--r--src/com/android/providers/downloads/Helpers.java24
-rw-r--r--src/com/android/providers/downloads/StorageManager.java94
4 files changed, 75 insertions, 77 deletions
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java
index ed793aa..25d5901 100644
--- a/src/com/android/providers/downloads/DownloadProvider.java
+++ b/src/com/android/providers/downloads/DownloadProvider.java
@@ -710,15 +710,26 @@ public final class DownloadProvider extends ContentProvider {
if (path == null) {
throw new IllegalArgumentException("Invalid file URI: " + uri);
}
-
- final String phoneStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
- String sdCardStoragePath = null;
- if (StorageManager.isSecondStorageSupported(getContext())) {
- sdCardStoragePath = StorageManager.getExternalStorageDirectory(getContext());
- }
- if (!path.startsWith(phoneStoragePath)
- && !(sdCardStoragePath != null && path.startsWith(sdCardStoragePath))) {
- throw new SecurityException("Destination must be on external storage: " + uri);
+ try {
+ boolean isValidExternalPath = false;
+ final String canonicalPath = new File(path).getCanonicalPath();
+ final String externalPath = Environment.getExternalStorageDirectory().getAbsolutePath();
+ final List<String> secondaryPaths = StorageManager.getSecondaryStoragePaths(getContext());
+ if (canonicalPath.startsWith(externalPath)) {
+ isValidExternalPath = true;
+ } else {
+ for (String secondaryPath : secondaryPaths) {
+ if (canonicalPath.startsWith(secondaryPath)) {
+ isValidExternalPath = true;
+ break;
+ }
+ }
+ }
+ if (!isValidExternalPath) {
+ throw new SecurityException("Destination must be on external storage: " + uri);
+ }
+ } catch (IOException e) {
+ throw new SecurityException("Problem resolving path: " + uri);
}
}
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index 517d8f8..88cd916 100755
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -583,7 +583,7 @@ public class DownloadThread implements Runnable {
*/
private void writeDataToDestination(State state, byte[] data, int bytesRead, OutputStream out)
throws StopRequestException {
- mStorageManager.verifySpaceBeforeWritingToFile(mContext,
+ mStorageManager.verifySpaceBeforeWritingToFile(
mInfo.mDestination, state.mFilename, bytesRead);
boolean forceVerified = false;
@@ -595,8 +595,7 @@ public class DownloadThread implements Runnable {
// TODO: better differentiate between DRM and disk failures
if (!forceVerified) {
// couldn't write to file. are we out of space? check.
- mStorageManager.verifySpace(mContext, mInfo.mDestination,
- state.mFilename, bytesRead);
+ mStorageManager.verifySpace(mInfo.mDestination, state.mFilename, bytesRead);
forceVerified = true;
} else {
throw new StopRequestException(Downloads.Impl.STATUS_FILE_ERROR,
diff --git a/src/com/android/providers/downloads/Helpers.java b/src/com/android/providers/downloads/Helpers.java
index 0739eea..40cf5e3 100644
--- a/src/com/android/providers/downloads/Helpers.java
+++ b/src/com/android/providers/downloads/Helpers.java
@@ -28,6 +28,7 @@ import android.webkit.MimeTypeMap;
import java.io.File;
import java.io.IOException;
+import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;
@@ -92,7 +93,7 @@ public class Helpers {
path = chooseFilename(url, hint, contentDisposition, contentLocation,
destination);
}
- storageManager.verifySpace(context, destination, path, contentLength);
+ storageManager.verifySpace(destination, path, contentLength);
if (DownloadDrmHelper.isDrmConvertNeeded(mimeType)) {
path = DownloadDrmHelper.modifyDrmFwLockFileExtension(path);
}
@@ -351,8 +352,9 @@ public class Helpers {
/**
* Checks whether the filename looks legitimate
*/
- static boolean isFilenameValid(String filename, File downloadsDataDir) {
+ static boolean isFilenameValid(Context context, String filename, File downloadsDataDir) {
final String[] whitelist;
+ final List<String> secondaryStoragePaths = StorageManager.getSecondaryStoragePaths(context);
try {
filename = new File(filename).getCanonicalPath();
whitelist = new String[] {
@@ -371,19 +373,13 @@ public class Helpers {
}
}
- return false;
- }
+ for (String test : secondaryStoragePaths) {
+ if (filename.startsWith(test)) {
+ return true;
+ }
+ }
- /**
- * Checks whether the filename looks legitimate
- */
- static boolean isFilenameValid(Context context, String filename, File downloadsDataDir) {
- filename = filename.replaceFirst("/+", "/"); // normalize leading slashes
- return filename.startsWith(Environment.getDownloadCacheDirectory().toString())
- || filename.startsWith(downloadsDataDir.toString())
- || filename.startsWith(Environment.getExternalStorageDirectory().toString())
- || (StorageManager.isSecondStorageSupported(context)
- && filename.startsWith(StorageManager.getExternalStorageDirectory(context)));
+ return false;
}
/**
diff --git a/src/com/android/providers/downloads/StorageManager.java b/src/com/android/providers/downloads/StorageManager.java
index 4194ec8..41592f4 100644
--- a/src/com/android/providers/downloads/StorageManager.java
+++ b/src/com/android/providers/downloads/StorageManager.java
@@ -19,7 +19,6 @@ package com.android.providers.downloads;
import static com.android.providers.downloads.Constants.LOGV;
import static com.android.providers.downloads.Constants.TAG;
-import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.res.Resources;
@@ -65,6 +64,9 @@ class StorageManager {
/** see {@link Environment#getExternalStorageDirectory()} */
private final File mExternalStorageDir;
+ /** list of secondary external storage paths */
+ private final List<String> mSecondaryStoragePaths;
+
/** see {@link Environment#getDownloadCacheDirectory()} */
private final File mSystemCacheDir;
@@ -79,20 +81,14 @@ class StorageManager {
/** misc members */
private final Context mContext;
- private static String sdCardStorageDir;
- private static final String LOGTAG = "StorageManager";
public StorageManager(Context context) {
mContext = context;
mDownloadDataDir = getDownloadDataDirectory(context);
mExternalStorageDir = Environment.getExternalStorageDirectory();
mSystemCacheDir = Environment.getDownloadCacheDirectory();
+ mSecondaryStoragePaths = getSecondaryStoragePaths(context);
startThreadToCleanupDatabaseAndPurgeFileSystem();
- if (isSecondStorageSupported(context)) {
- sdCardStorageDir = getExternalStorageDirectory(context);
- } else {
- sdCardStorageDir = null;
- }
}
/** How often should database and filesystem be cleaned up to remove spurious files
@@ -125,20 +121,20 @@ class StorageManager {
mCleanupThread.start();
}
- void verifySpaceBeforeWritingToFile(Context context, int destination, String path, long length)
+ void verifySpaceBeforeWritingToFile(int destination, String path, long length)
throws StopRequestException {
// do this check only once for every 1MB of downloaded data
if (incrementBytesDownloadedSinceLastCheckOnSpace(length) <
FREQUENCY_OF_CHECKS_ON_SPACE_AVAILABILITY) {
return;
}
- verifySpace(context, destination, path, length);
+ verifySpace(destination, path, length);
}
- void verifySpace(Context context, int destination, String path,
- long length) throws StopRequestException {
+ void verifySpace(int destination, String path, long length) throws StopRequestException {
resetBytesDownloadedSinceLastCheckOnSpace();
File dir = null;
+ boolean isSecondaryStorage = false;
if (Constants.LOGV) {
Log.i(Constants.TAG, "in verifySpace, destination: " + destination +
", path: " + path + ", length: " + length);
@@ -159,14 +155,25 @@ class StorageManager {
dir = mSystemCacheDir;
break;
case Downloads.Impl.DESTINATION_FILE_URI:
- if (isSecondStorageSupported(context) && path.startsWith(sdCardStorageDir)) {
- dir = new File(sdCardStorageDir);
- } else if (path.startsWith(mExternalStorageDir.getPath())) {
+ if (path.startsWith(mExternalStorageDir.getPath())) {
dir = mExternalStorageDir;
- } else if (path.startsWith(mDownloadDataDir.getPath())) {
- dir = mDownloadDataDir;
- } else if (path.startsWith(mSystemCacheDir.getPath())) {
- dir = mSystemCacheDir;
+ } else {
+ for (String secondaryPath : mSecondaryStoragePaths) {
+ if (path.startsWith(secondaryPath)) {
+ isSecondaryStorage = true;
+ dir = new File(secondaryPath);
+ break;
+ }
+ }
+ }
+ // TODO - should only check external storage?
+ if (dir == null) {
+ if (path.startsWith(mDownloadDataDir.getPath())) {
+ dir = mDownloadDataDir;
+ }
+ else if (path.startsWith(mSystemCacheDir.getPath())) {
+ dir = mSystemCacheDir;
+ }
}
break;
}
@@ -174,7 +181,7 @@ class StorageManager {
throw new IllegalStateException("invalid combination of destination: " + destination +
", path: " + path);
}
- findSpace(context, dir, length, destination);
+ findSpace(dir, length, destination, isSecondaryStorage);
}
/**
@@ -182,18 +189,20 @@ class StorageManager {
* specified by the input param(targetBytes).
* returns true if found. false otherwise.
*/
- private synchronized void findSpace(Context context, File root, long targetBytes,
- int destination) throws StopRequestException {
+ private synchronized void findSpace(File root, long targetBytes, int destination,
+ boolean isSecondaryStorage) throws StopRequestException {
if (targetBytes == 0) {
return;
}
- if (!(isSecondStorageSupported(context) && root.getPath().startsWith(sdCardStorageDir))) {
- if (destination == Downloads.Impl.DESTINATION_FILE_URI ||
- destination == Downloads.Impl.DESTINATION_EXTERNAL) {
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- throw new StopRequestException(Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR,
- "external media not mounted");
- }
+ if (root == mExternalStorageDir) {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new StopRequestException(Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR,
+ "external media not mounted");
+ }
+ } else if (isSecondaryStorage) {
+ if (!Environment.getStorageState(root).equals(Environment.MEDIA_MOUNTED)) {
+ throw new StopRequestException(Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR,
+ "external media not mounted");
}
}
// is there enough space in the file system of the given param 'root'.
@@ -484,35 +493,18 @@ class StorageManager {
mBytesDownloadedSinceLastCheckOnSpace = 0;
}
- /**
- * Whether the device supports second storage
- * @return boolean true support second storage, false does not
- */
- public static boolean isSecondStorageSupported(Context context) {
+ public static List<String> getSecondaryStoragePaths(Context context) {
+ List<String> secondaryPaths = new ArrayList<String>();
android.os.storage.StorageManager storageManager =
(android.os.storage.StorageManager) context
.getSystemService(Context.STORAGE_SERVICE);
StorageVolume[] volumes = storageManager.getVolumeList();
for (int i = 0; i < volumes.length; i++) {
- if (!volumes[i].isPrimary() && volumes[i].allowMassStorage()) {
- return true;
+ if (!volumes[i].isPrimary()) {
+ secondaryPaths.add(volumes[i].getPath());
}
}
- return false;
+ return secondaryPaths;
}
- public static String getExternalStorageDirectory(Context context) {
- String sdCardDir = null;
- android.os.storage.StorageManager storageManager =
- (android.os.storage.StorageManager) context
- .getSystemService(Context.STORAGE_SERVICE);
- StorageVolume[] volumes = storageManager.getVolumeList();
- for (int i = 0; i < volumes.length; i++) {
- if (volumes[i].isRemovable() && volumes[i].allowMassStorage()) {
- sdCardDir = volumes[i].getPath();
- break;
- }
- }
- return sdCardDir;
- }
}