diff options
author | qqzhou <qqzhou@codeaurora.org> | 2013-12-05 17:02:33 +0800 |
---|---|---|
committer | Adnan <adnan@cyngn.com> | 2014-08-26 17:06:43 -0700 |
commit | f668ad5ed0b6885052118725f360de5c68c96f36 (patch) | |
tree | 2611155cff1388a55b9df34bb36c9bff50bf92c3 /src | |
parent | 58b97fe09205eea731f5a51d7be0a83230550ab8 (diff) | |
download | android_packages_providers_DownloadProvider-f668ad5ed0b6885052118725f360de5c68c96f36.tar.gz android_packages_providers_DownloadProvider-f668ad5ed0b6885052118725f360de5c68c96f36.tar.bz2 android_packages_providers_DownloadProvider-f668ad5ed0b6885052118725f360de5c68c96f36.zip |
DownloadProvider: add to support download into sdcard storage
When insert into downloads database to start a new download,
will check file uri destination is valid or not, currently it
only support phone storage downloading, what we do is to add
supporting sdcard storage downloading, this will make download
save path setting feature work well.
Change-Id: I7995ae63ec5769103d7ad66bcd677e383ef7f440
Diffstat (limited to 'src')
4 files changed, 66 insertions, 16 deletions
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java index 0928fdfc..132deb9a 100644 --- a/src/com/android/providers/downloads/DownloadProvider.java +++ b/src/com/android/providers/downloads/DownloadProvider.java @@ -710,14 +710,15 @@ public final class DownloadProvider extends ContentProvider { if (path == null) { throw new IllegalArgumentException("Invalid file URI: " + uri); } - try { - final String canonicalPath = new File(path).getCanonicalPath(); - final String externalPath = Environment.getExternalStorageDirectory().getAbsolutePath(); - if (!canonicalPath.startsWith(externalPath)) { - throw new SecurityException("Destination must be on external storage: " + uri); - } - } catch (IOException e) { - throw new SecurityException("Problem resolving path: " + uri); + + final String phoneStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath(); + String sdCardStoragePath = null; + if (StorageManager.isSecondStorageSupported()) { + sdCardStoragePath = StorageManager.getExternalStorageDirectory(getContext()); + } + if (!path.startsWith(phoneStoragePath) + && !(sdCardStoragePath != null && path.startsWith(sdCardStoragePath))) { + throw new SecurityException("Destination must be on external storage: " + uri); } } @@ -1209,7 +1210,7 @@ public final class DownloadProvider extends ContentProvider { if (path == null) { throw new FileNotFoundException("No filename found."); } - if (!Helpers.isFilenameValid(path, mDownloadsDataDir)) { + if (!Helpers.isFilenameValid(getContext(), path, mDownloadsDataDir)) { throw new FileNotFoundException("Invalid filename: " + path); } diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java index 9d5274c4..88cd9162 100755 --- a/src/com/android/providers/downloads/DownloadThread.java +++ b/src/com/android/providers/downloads/DownloadThread.java @@ -769,7 +769,7 @@ public class DownloadThread implements Runnable { Log.i(Constants.TAG, "have run thread before for id: " + mInfo.mId + ", and state.mFilename: " + state.mFilename); } - if (!Helpers.isFilenameValid(state.mFilename, + if (!Helpers.isFilenameValid(mContext, state.mFilename, mStorageManager.getDownloadDataDirectory())) { // this should never happen 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 3562dac7..d9b38b50 100644 --- a/src/com/android/providers/downloads/Helpers.java +++ b/src/com/android/providers/downloads/Helpers.java @@ -375,6 +375,18 @@ public class Helpers { } /** + * 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() && filename.startsWith(StorageManager + .getExternalStorageDirectory(context))); + } + + /** * Checks whether this looks like a legitimate selection parameter */ public static void validateSelection(String selection, Set<String> allowedColumns) { diff --git a/src/com/android/providers/downloads/StorageManager.java b/src/com/android/providers/downloads/StorageManager.java index deb412e7..a0ceae6a 100644 --- a/src/com/android/providers/downloads/StorageManager.java +++ b/src/com/android/providers/downloads/StorageManager.java @@ -19,6 +19,7 @@ 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; @@ -27,6 +28,7 @@ import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.Environment; import android.os.StatFs; +import android.os.storage.StorageVolume; import android.provider.Downloads; import android.text.TextUtils; import android.util.Log; @@ -77,6 +79,8 @@ class StorageManager { /** misc members */ private final Context mContext; + private static String sdCardStorageDir; + private static final String LOGTAG = "StorageManager"; public StorageManager(Context context) { mContext = context; @@ -84,6 +88,11 @@ class StorageManager { mExternalStorageDir = Environment.getExternalStorageDirectory(); mSystemCacheDir = Environment.getDownloadCacheDirectory(); startThreadToCleanupDatabaseAndPurgeFileSystem(); + if (isSecondStorageSupported()) { + sdCardStorageDir = getExternalStorageDirectory(context); + } else { + sdCardStorageDir = null; + } } /** How often should database and filesystem be cleaned up to remove spurious files @@ -149,7 +158,9 @@ class StorageManager { dir = mSystemCacheDir; break; case Downloads.Impl.DESTINATION_FILE_URI: - if (path.startsWith(mExternalStorageDir.getPath())) { + if (isSecondStorageSupported() && path.startsWith(sdCardStorageDir)) { + dir = new File(sdCardStorageDir); + } else if (path.startsWith(mExternalStorageDir.getPath())) { dir = mExternalStorageDir; } else if (path.startsWith(mDownloadDataDir.getPath())) { dir = mDownloadDataDir; @@ -175,11 +186,13 @@ class StorageManager { if (targetBytes == 0) { return; } - 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 (!(isSecondStorageSupported() && 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"); + } } } // is there enough space in the file system of the given param 'root'. @@ -469,4 +482,28 @@ class StorageManager { private synchronized void resetBytesDownloadedSinceLastCheckOnSpace() { mBytesDownloadedSinceLastCheckOnSpace = 0; } + + /** + * Whether support Second Storage + * + * @return boolean true support Second Storage, false will be not + */ + public static boolean isSecondStorageSupported() { + return true; + } + + 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; + } } |