diff options
-rw-r--r-- | AndroidManifest.xml | 6 | ||||
-rw-r--r-- | res/values/strings.xml | 9 | ||||
-rw-r--r-- | src/com/android/providers/downloads/DownloadProvider.java | 21 |
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"><Untitled></string> diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java index d72b1460..74fd2792 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)) { @@ -841,7 +852,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 "); |