summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Howard <showard@google.com>2010-07-20 16:32:31 -0700
committerSteve Howard <showard@google.com>2010-07-23 15:14:45 -0700
commit71aab521efba9b28779541440c797220ec98ac97 (patch)
tree592cfe9a02dddf9e862934146536623050724355
parentb06b739b078ce4b00600487cfec31659647bf31f (diff)
downloadandroid_packages_providers_DownloadProvider-71aab521efba9b28779541440c797220ec98ac97.tar.gz
android_packages_providers_DownloadProvider-71aab521efba9b28779541440c797220ec98ac97.tar.bz2
android_packages_providers_DownloadProvider-71aab521efba9b28779541440c797220ec98ac97.zip
Support for non-purgeable downloads through the public API.
This change adds a permission, android.permission.DOWNLOAD_CACHE_NON_PURGEABLE. When an app has this permission, any downloads it requests through the public API to the download cache will automatically become non-purgeable, i.e. they'll never be automatically deleted by the download manager to free up space. This is intended for use only by the system updater. Change-Id: I35cdd44f7e5d46bc70443d1a9743f61a51395ddb
-rw-r--r--AndroidManifest.xml6
-rw-r--r--res/values/strings.xml9
-rw-r--r--src/com/android/providers/downloads/DownloadProvider.java21
3 files changed, 31 insertions, 5 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 20fe6ca6..d6c85d34 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -21,6 +21,12 @@
android:description="@string/permdesc_downloadCompletedIntent"
android:protectionLevel="signature" />
+ <!-- Allows to download non-purgeable files to the cache partition through the public API -->
+ <permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE"
+ android:label="@string/permlab_downloadCacheNonPurgeable"
+ android:description="@string/permdesc_downloadCacheNonPurgeable"
+ android:protectionLevel="dangerous"/>
+
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
<uses-permission android:name="android.permission.ACCESS_DRM" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7e40b608..0bc5c09c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -73,6 +73,15 @@
<string name="permdesc_seeAllExternal">Allows the application to see all
downloads to the SD card, regardless of which application downloaded
them.</string>
+
+ <string name="permlab_downloadCacheNonPurgeable">Download non-purgeable
+ files to the cache</string>
+ <string name="permdesc_downloadCacheNonPurgeable">Allows the application to
+ download files to the download cache through the public API which will not
+ be automatically deleted when the download manager needs more space.
+ Malicious applications can use this to block other applications from using
+ the download cache.</string>
+
<!-- This is the title that is used when displaying the notification
for a download that doesn't have a title associated with it. -->
<string name="download_unknown_title">&lt;Untitled&gt;</string>
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java
index 2c0a2645..a116f87d 100644
--- a/src/com/android/providers/downloads/DownloadProvider.java
+++ b/src/com/android/providers/downloads/DownloadProvider.java
@@ -337,6 +337,11 @@ public final class DownloadProvider extends ContentProvider {
copyBoolean(Downloads.Impl.COLUMN_NO_INTEGRITY, values, filteredValues);
copyString(Downloads.Impl.COLUMN_FILE_NAME_HINT, values, filteredValues);
copyString(Downloads.Impl.COLUMN_MIME_TYPE, values, filteredValues);
+
+ copyBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API, values, filteredValues);
+ boolean isPublicApi =
+ values.getAsBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API) == Boolean.TRUE;
+
Integer dest = values.getAsInteger(Downloads.Impl.COLUMN_DESTINATION);
if (dest != null) {
if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED)
@@ -346,6 +351,16 @@ public final class DownloadProvider extends ContentProvider {
&& dest != Downloads.Impl.DESTINATION_FILE_URI) {
throw new SecurityException("unauthorized destination code");
}
+ // for public API behavior, if an app has CACHE_NON_PURGEABLE permission, automatically
+ // switch to non-purgeable download
+ boolean hasNonPurgeablePermission =
+ getContext().checkCallingPermission(
+ Downloads.Impl.PERMISSION_CACHE_NON_PURGEABLE)
+ == PackageManager.PERMISSION_GRANTED;
+ if (isPublicApi && dest == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE
+ && hasNonPurgeablePermission) {
+ dest = Downloads.Impl.DESTINATION_CACHE_PARTITION;
+ }
if (dest == Downloads.Impl.DESTINATION_FILE_URI) {
getContext().enforcePermission(
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
@@ -372,10 +387,6 @@ public final class DownloadProvider extends ContentProvider {
filteredValues.put(Downloads.Impl.COLUMN_LAST_MODIFICATION,
mSystemFacade.currentTimeMillis());
- copyBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API, values, filteredValues);
- boolean isPublicApi =
- values.getAsBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API) == Boolean.TRUE;
-
String pckg = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
String clazz = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
if (pckg != null && (clazz != null || isPublicApi)) {
@@ -846,7 +857,7 @@ public final class DownloadProvider extends ContentProvider {
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
-
+
private void appendClause(StringBuilder whereClause, String newClause) {
if (whereClause.length() != 0) {
whereClause.append(" AND ");