summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers')
-rw-r--r--src/com/android/providers/downloads/DownloadInfo.java24
-rw-r--r--src/com/android/providers/downloads/DownloadNotification.java81
-rw-r--r--src/com/android/providers/downloads/DownloadProvider.java252
-rw-r--r--src/com/android/providers/downloads/DownloadReceiver.java39
-rw-r--r--src/com/android/providers/downloads/DownloadService.java179
-rw-r--r--src/com/android/providers/downloads/DownloadThread.java123
-rw-r--r--src/com/android/providers/downloads/Helpers.java107
7 files changed, 443 insertions, 362 deletions
diff --git a/src/com/android/providers/downloads/DownloadInfo.java b/src/com/android/providers/downloads/DownloadInfo.java
index 88cdede2..81895439 100644
--- a/src/com/android/providers/downloads/DownloadInfo.java
+++ b/src/com/android/providers/downloads/DownloadInfo.java
@@ -90,10 +90,10 @@ public class DownloadInfo {
public void sendIntentIfRequested(Uri contentUri, Context context) {
if (mPackage != null && mClass != null) {
- Intent intent = new Intent(Downloads.ACTION_DOWNLOAD_COMPLETED);
+ Intent intent = new Intent(Downloads.Impl.ACTION_DOWNLOAD_COMPLETED);
intent.setClassName(mPackage, mClass);
if (mExtras != null) {
- intent.putExtra(Downloads.COLUMN_NOTIFICATION_EXTRAS, mExtras);
+ intent.putExtra(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, mExtras);
}
// We only send the content: URI, for security reasons. Otherwise, malicious
// applications would have an easier time spoofing download results by
@@ -121,7 +121,7 @@ public class DownloadInfo {
* should be started.
*/
public boolean isReadyToStart(long now) {
- if (mControl == Downloads.CONTROL_PAUSED) {
+ if (mControl == Downloads.Impl.CONTROL_PAUSED) {
// the download is paused, so it's not going to start
return false;
}
@@ -129,16 +129,16 @@ public class DownloadInfo {
// status hasn't been initialized yet, this is a new download
return true;
}
- if (mStatus == Downloads.STATUS_PENDING) {
+ if (mStatus == Downloads.Impl.STATUS_PENDING) {
// download is explicit marked as ready to start
return true;
}
- if (mStatus == Downloads.STATUS_RUNNING) {
+ if (mStatus == Downloads.Impl.STATUS_RUNNING) {
// download was interrupted (process killed, loss of power) while it was running,
// without a chance to update the database
return true;
}
- if (mStatus == Downloads.STATUS_RUNNING_PAUSED) {
+ if (mStatus == Downloads.Impl.STATUS_RUNNING_PAUSED) {
if (mNumFailed == 0) {
// download is waiting for network connectivity to return before it can resume
return true;
@@ -160,7 +160,7 @@ public class DownloadInfo {
* by checking the status.
*/
public boolean isReadyToRestart(long now) {
- if (mControl == Downloads.CONTROL_PAUSED) {
+ if (mControl == Downloads.Impl.CONTROL_PAUSED) {
// the download is paused, so it's not going to restart
return false;
}
@@ -168,11 +168,11 @@ public class DownloadInfo {
// download hadn't been initialized yet
return true;
}
- if (mStatus == Downloads.STATUS_PENDING) {
+ if (mStatus == Downloads.Impl.STATUS_PENDING) {
// download is explicit marked as ready to start
return true;
}
- if (mStatus == Downloads.STATUS_RUNNING_PAUSED) {
+ if (mStatus == Downloads.Impl.STATUS_RUNNING_PAUSED) {
if (mNumFailed == 0) {
// download is waiting for network connectivity to return before it can resume
return true;
@@ -190,10 +190,10 @@ public class DownloadInfo {
* completion.
*/
public boolean hasCompletionNotification() {
- if (!Downloads.isStatusCompleted(mStatus)) {
+ if (!Downloads.Impl.isStatusCompleted(mStatus)) {
return false;
}
- if (mVisibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
+ if (mVisibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
return true;
}
return false;
@@ -206,7 +206,7 @@ public class DownloadInfo {
if (!available) {
return false;
}
- if (mDestination == Downloads.DESTINATION_CACHE_PARTITION_NOROAMING) {
+ if (mDestination == Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING) {
return !roaming;
} else {
return true;
diff --git a/src/com/android/providers/downloads/DownloadNotification.java b/src/com/android/providers/downloads/DownloadNotification.java
index f7c10073..e9c0d4e6 100644
--- a/src/com/android/providers/downloads/DownloadNotification.java
+++ b/src/com/android/providers/downloads/DownloadNotification.java
@@ -43,15 +43,16 @@ class DownloadNotification {
static final String LOGTAG = "DownloadNotification";
static final String WHERE_RUNNING =
- "(" + Downloads.COLUMN_STATUS + " >= '100') AND (" +
- Downloads.COLUMN_STATUS + " <= '199') AND (" +
- Downloads.COLUMN_VISIBILITY + " IS NULL OR " +
- Downloads.COLUMN_VISIBILITY + " == '" + Downloads.VISIBILITY_VISIBLE + "' OR " +
- Downloads.COLUMN_VISIBILITY +
- " == '" + Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + "')";
+ "(" + Downloads.Impl.COLUMN_STATUS + " >= '100') AND (" +
+ Downloads.Impl.COLUMN_STATUS + " <= '199') AND (" +
+ Downloads.Impl.COLUMN_VISIBILITY + " IS NULL OR " +
+ Downloads.Impl.COLUMN_VISIBILITY + " == '" + Downloads.Impl.VISIBILITY_VISIBLE + "' OR " +
+ Downloads.Impl.COLUMN_VISIBILITY +
+ " == '" + Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + "')";
static final String WHERE_COMPLETED =
- Downloads.COLUMN_STATUS + " >= '200' AND " +
- Downloads.COLUMN_VISIBILITY + " == '" + Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + "'";
+ Downloads.Impl.COLUMN_STATUS + " >= '200' AND " +
+ Downloads.Impl.COLUMN_VISIBILITY +
+ " == '" + Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + "'";
/**
@@ -110,17 +111,17 @@ class DownloadNotification {
private void updateActiveNotification() {
// Active downloads
Cursor c = mContext.getContentResolver().query(
- Downloads.CONTENT_URI, new String [] {
- Downloads._ID,
- Downloads.COLUMN_TITLE,
- Downloads.COLUMN_DESCRIPTION,
- Downloads.COLUMN_NOTIFICATION_PACKAGE,
- Downloads.COLUMN_NOTIFICATION_CLASS,
- Downloads.COLUMN_CURRENT_BYTES,
- Downloads.COLUMN_TOTAL_BYTES,
- Downloads.COLUMN_STATUS, Downloads._DATA
+ Downloads.Impl.CONTENT_URI, new String [] {
+ Downloads.Impl._ID,
+ Downloads.Impl.COLUMN_TITLE,
+ Downloads.Impl.COLUMN_DESCRIPTION,
+ Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
+ Downloads.Impl.COLUMN_NOTIFICATION_CLASS,
+ Downloads.Impl.COLUMN_CURRENT_BYTES,
+ Downloads.Impl.COLUMN_TOTAL_BYTES,
+ Downloads.Impl.COLUMN_STATUS
},
- WHERE_RUNNING, null, Downloads._ID);
+ WHERE_RUNNING, null, Downloads.Impl._ID);
if (c == null) {
return;
@@ -135,7 +136,6 @@ class DownloadNotification {
final int currentBytesColumn = 5;
final int totalBytesColumn = 6;
final int statusColumn = 7;
- final int filenameColumnId = 8;
// Collate the notifications
mNotifications.clear();
@@ -143,6 +143,7 @@ class DownloadNotification {
String packageName = c.getString(ownerColumn);
int max = c.getInt(totalBytesColumn);
int progress = c.getInt(currentBytesColumn);
+ long id = c.getLong(idColumn);
String title = c.getString(titleColumn);
if (title == null || title.length() == 0) {
title = mContext.getResources().getString(
@@ -152,7 +153,7 @@ class DownloadNotification {
mNotifications.get(packageName).addItem(title, progress, max);
} else {
NotificationItem item = new NotificationItem();
- item.mId = c.getInt(idColumn);
+ item.mId = (int) id;
item.mPackageName = packageName;
item.mDescription = c.getString(descColumn);
String className = c.getString(classOwnerColumn);
@@ -202,7 +203,7 @@ class DownloadNotification {
Intent intent = new Intent(Constants.ACTION_LIST);
intent.setClassName("com.android.providers.downloads",
DownloadReceiver.class.getName());
- intent.setData(Uri.parse(Downloads.CONTENT_URI + "/" + item.mId));
+ intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + item.mId));
intent.putExtra("multiple", item.mTitleCount > 1);
n.contentIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
@@ -215,20 +216,19 @@ class DownloadNotification {
private void updateCompletedNotification() {
// Completed downloads
Cursor c = mContext.getContentResolver().query(
- Downloads.CONTENT_URI, new String [] {
- Downloads._ID,
- Downloads.COLUMN_TITLE,
- Downloads.COLUMN_DESCRIPTION,
- Downloads.COLUMN_NOTIFICATION_PACKAGE,
- Downloads.COLUMN_NOTIFICATION_CLASS,
- Downloads.COLUMN_CURRENT_BYTES,
- Downloads.COLUMN_TOTAL_BYTES,
- Downloads.COLUMN_STATUS,
- Downloads._DATA,
- Downloads.COLUMN_LAST_MODIFICATION,
- Downloads.COLUMN_DESTINATION
+ Downloads.Impl.CONTENT_URI, new String [] {
+ Downloads.Impl._ID,
+ Downloads.Impl.COLUMN_TITLE,
+ Downloads.Impl.COLUMN_DESCRIPTION,
+ Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
+ Downloads.Impl.COLUMN_NOTIFICATION_CLASS,
+ Downloads.Impl.COLUMN_CURRENT_BYTES,
+ Downloads.Impl.COLUMN_TOTAL_BYTES,
+ Downloads.Impl.COLUMN_STATUS,
+ Downloads.Impl.COLUMN_LAST_MODIFICATION,
+ Downloads.Impl.COLUMN_DESTINATION
},
- WHERE_COMPLETED, null, Downloads._ID);
+ WHERE_COMPLETED, null, Downloads.Impl._ID);
if (c == null) {
return;
@@ -243,31 +243,31 @@ class DownloadNotification {
final int currentBytesColumn = 5;
final int totalBytesColumn = 6;
final int statusColumn = 7;
- final int filenameColumnId = 8;
- final int lastModColumnId = 9;
- final int destinationColumnId = 10;
+ final int lastModColumnId = 8;
+ final int destinationColumnId = 9;
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
// Add the notifications
Notification n = new Notification();
n.icon = android.R.drawable.stat_sys_download_done;
+ long id = c.getLong(idColumn);
String title = c.getString(titleColumn);
if (title == null || title.length() == 0) {
title = mContext.getResources().getString(
R.string.download_unknown_title);
}
- Uri contentUri = Uri.parse(Downloads.CONTENT_URI + "/" + c.getInt(idColumn));
+ Uri contentUri = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + id);
String caption;
Intent intent;
- if (Downloads.isStatusError(c.getInt(statusColumn))) {
+ if (Downloads.Impl.isStatusError(c.getInt(statusColumn))) {
caption = mContext.getResources()
.getString(R.string.notification_download_failed);
intent = new Intent(Constants.ACTION_LIST);
} else {
caption = mContext.getResources()
.getString(R.string.notification_download_complete);
- if (c.getInt(destinationColumnId) == Downloads.DESTINATION_EXTERNAL) {
+ if (c.getInt(destinationColumnId) == Downloads.Impl.DESTINATION_EXTERNAL) {
intent = new Intent(Constants.ACTION_OPEN);
} else {
intent = new Intent(Constants.ACTION_LIST);
@@ -276,6 +276,7 @@ class DownloadNotification {
intent.setClassName("com.android.providers.downloads",
DownloadReceiver.class.getName());
intent.setData(contentUri);
+
n.when = c.getLong(lastModColumnId);
n.setLatestEventInfo(mContext, title, caption,
PendingIntent.getBroadcast(mContext, 0, intent, 0));
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java
index f0190fd1..d7c24f9a 100644
--- a/src/com/android/providers/downloads/DownloadProvider.java
+++ b/src/com/android/providers/downloads/DownloadProvider.java
@@ -21,7 +21,9 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.UriMatcher;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.database.CrossProcessCursor;
import android.database.Cursor;
import android.database.CursorWindow;
@@ -76,21 +78,21 @@ public final class DownloadProvider extends ContentProvider {
}
private static final String[] sAppReadableColumnsArray = new String[] {
- Downloads._ID,
- Downloads.COLUMN_APP_DATA,
- Downloads._DATA,
- Downloads.COLUMN_MIME_TYPE,
- Downloads.COLUMN_VISIBILITY,
- Downloads.COLUMN_DESTINATION,
- Downloads.COLUMN_CONTROL,
- Downloads.COLUMN_STATUS,
- Downloads.COLUMN_LAST_MODIFICATION,
- Downloads.COLUMN_NOTIFICATION_PACKAGE,
- Downloads.COLUMN_NOTIFICATION_CLASS,
- Downloads.COLUMN_TOTAL_BYTES,
- Downloads.COLUMN_CURRENT_BYTES,
- Downloads.COLUMN_TITLE,
- Downloads.COLUMN_DESCRIPTION
+ Downloads.Impl._ID,
+ Downloads.Impl.COLUMN_APP_DATA,
+ Downloads.Impl._DATA,
+ Downloads.Impl.COLUMN_MIME_TYPE,
+ Downloads.Impl.COLUMN_VISIBILITY,
+ Downloads.Impl.COLUMN_DESTINATION,
+ Downloads.Impl.COLUMN_CONTROL,
+ Downloads.Impl.COLUMN_STATUS,
+ Downloads.Impl.COLUMN_LAST_MODIFICATION,
+ Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
+ Downloads.Impl.COLUMN_NOTIFICATION_CLASS,
+ Downloads.Impl.COLUMN_TOTAL_BYTES,
+ Downloads.Impl.COLUMN_CURRENT_BYTES,
+ Downloads.Impl.COLUMN_TITLE,
+ Downloads.Impl.COLUMN_DESCRIPTION
};
private static HashSet<String> sAppReadableColumnsSet;
@@ -104,6 +106,10 @@ public final class DownloadProvider extends ContentProvider {
/** The database that lies underneath this content provider */
private SQLiteOpenHelper mOpenHelper = null;
+ /** List of uids that can access the downloads */
+ private int mSystemUid = -1;
+ private int mDefContainerUid = -1;
+
/**
* Creates and updated database on demand when opening it.
* Helper class to create database the first time the provider is
@@ -167,6 +173,21 @@ public final class DownloadProvider extends ContentProvider {
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
+ // Initialize the system uid
+ mSystemUid = Process.SYSTEM_UID;
+ // Initialize the default container uid. Package name hardcoded
+ // for now.
+ ApplicationInfo appInfo = null;
+ try {
+ appInfo = getContext().getPackageManager().
+ getApplicationInfo("com.android.defcontainer", 0);
+ } catch (NameNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if (appInfo != null) {
+ mDefContainerUid = appInfo.uid;
+ }
return true;
}
@@ -199,35 +220,35 @@ public final class DownloadProvider extends ContentProvider {
private void createTable(SQLiteDatabase db) {
try {
db.execSQL("CREATE TABLE " + DB_TABLE + "(" +
- Downloads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
- Downloads.COLUMN_URI + " TEXT, " +
+ Downloads.Impl._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ Downloads.Impl.COLUMN_URI + " TEXT, " +
Constants.RETRY_AFTER_X_REDIRECT_COUNT + " INTEGER, " +
- Downloads.COLUMN_APP_DATA + " TEXT, " +
- Downloads.COLUMN_NO_INTEGRITY + " BOOLEAN, " +
- Downloads.COLUMN_FILE_NAME_HINT + " TEXT, " +
+ Downloads.Impl.COLUMN_APP_DATA + " TEXT, " +
+ Downloads.Impl.COLUMN_NO_INTEGRITY + " BOOLEAN, " +
+ Downloads.Impl.COLUMN_FILE_NAME_HINT + " TEXT, " +
Constants.OTA_UPDATE + " BOOLEAN, " +
- Downloads._DATA + " TEXT, " +
- Downloads.COLUMN_MIME_TYPE + " TEXT, " +
- Downloads.COLUMN_DESTINATION + " INTEGER, " +
+ Downloads.Impl._DATA + " TEXT, " +
+ Downloads.Impl.COLUMN_MIME_TYPE + " TEXT, " +
+ Downloads.Impl.COLUMN_DESTINATION + " INTEGER, " +
Constants.NO_SYSTEM_FILES + " BOOLEAN, " +
- Downloads.COLUMN_VISIBILITY + " INTEGER, " +
- Downloads.COLUMN_CONTROL + " INTEGER, " +
- Downloads.COLUMN_STATUS + " INTEGER, " +
+ Downloads.Impl.COLUMN_VISIBILITY + " INTEGER, " +
+ Downloads.Impl.COLUMN_CONTROL + " INTEGER, " +
+ Downloads.Impl.COLUMN_STATUS + " INTEGER, " +
Constants.FAILED_CONNECTIONS + " INTEGER, " +
- Downloads.COLUMN_LAST_MODIFICATION + " BIGINT, " +
- Downloads.COLUMN_NOTIFICATION_PACKAGE + " TEXT, " +
- Downloads.COLUMN_NOTIFICATION_CLASS + " TEXT, " +
- Downloads.COLUMN_NOTIFICATION_EXTRAS + " TEXT, " +
- Downloads.COLUMN_COOKIE_DATA + " TEXT, " +
- Downloads.COLUMN_USER_AGENT + " TEXT, " +
- Downloads.COLUMN_REFERER + " TEXT, " +
- Downloads.COLUMN_TOTAL_BYTES + " INTEGER, " +
- Downloads.COLUMN_CURRENT_BYTES + " INTEGER, " +
+ Downloads.Impl.COLUMN_LAST_MODIFICATION + " BIGINT, " +
+ Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE + " TEXT, " +
+ Downloads.Impl.COLUMN_NOTIFICATION_CLASS + " TEXT, " +
+ Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS + " TEXT, " +
+ Downloads.Impl.COLUMN_COOKIE_DATA + " TEXT, " +
+ Downloads.Impl.COLUMN_USER_AGENT + " TEXT, " +
+ Downloads.Impl.COLUMN_REFERER + " TEXT, " +
+ Downloads.Impl.COLUMN_TOTAL_BYTES + " INTEGER, " +
+ Downloads.Impl.COLUMN_CURRENT_BYTES + " INTEGER, " +
Constants.ETAG + " TEXT, " +
Constants.UID + " INTEGER, " +
- Downloads.COLUMN_OTHER_UID + " INTEGER, " +
- Downloads.COLUMN_TITLE + " TEXT, " +
- Downloads.COLUMN_DESCRIPTION + " TEXT, " +
+ Downloads.Impl.COLUMN_OTHER_UID + " INTEGER, " +
+ Downloads.Impl.COLUMN_TITLE + " TEXT, " +
+ Downloads.Impl.COLUMN_DESCRIPTION + " TEXT, " +
Constants.MEDIA_SCANNED + " BOOLEAN);");
} catch (SQLException ex) {
Log.e(Constants.TAG, "couldn't create table in downloads database");
@@ -263,70 +284,71 @@ public final class DownloadProvider extends ContentProvider {
ContentValues filteredValues = new ContentValues();
- copyString(Downloads.COLUMN_URI, values, filteredValues);
- copyString(Downloads.COLUMN_APP_DATA, values, filteredValues);
- copyBoolean(Downloads.COLUMN_NO_INTEGRITY, values, filteredValues);
- copyString(Downloads.COLUMN_FILE_NAME_HINT, values, filteredValues);
- copyString(Downloads.COLUMN_MIME_TYPE, values, filteredValues);
- Integer dest = values.getAsInteger(Downloads.COLUMN_DESTINATION);
+ copyString(Downloads.Impl.COLUMN_URI, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues);
+ 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);
+ Integer dest = values.getAsInteger(Downloads.Impl.COLUMN_DESTINATION);
if (dest != null) {
- if (getContext().checkCallingPermission(Downloads.PERMISSION_ACCESS_ADVANCED)
+ if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED)
!= PackageManager.PERMISSION_GRANTED
- && dest != Downloads.DESTINATION_EXTERNAL
- && dest != Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE) {
+ && dest != Downloads.Impl.DESTINATION_EXTERNAL
+ && dest != Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE) {
throw new SecurityException("unauthorized destination code");
}
- filteredValues.put(Downloads.COLUMN_DESTINATION, dest);
+ filteredValues.put(Downloads.Impl.COLUMN_DESTINATION, dest);
}
- Integer vis = values.getAsInteger(Downloads.COLUMN_VISIBILITY);
+ Integer vis = values.getAsInteger(Downloads.Impl.COLUMN_VISIBILITY);
if (vis == null) {
- if (dest == Downloads.DESTINATION_EXTERNAL) {
- filteredValues.put(Downloads.COLUMN_VISIBILITY,
- Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ if (dest == Downloads.Impl.DESTINATION_EXTERNAL) {
+ filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY,
+ Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
} else {
- filteredValues.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_HIDDEN);
+ filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY,
+ Downloads.Impl.VISIBILITY_HIDDEN);
}
} else {
- filteredValues.put(Downloads.COLUMN_VISIBILITY, vis);
+ filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, vis);
}
- copyInteger(Downloads.COLUMN_CONTROL, values, filteredValues);
- filteredValues.put(Downloads.COLUMN_STATUS, Downloads.STATUS_PENDING);
- filteredValues.put(Downloads.COLUMN_LAST_MODIFICATION, System.currentTimeMillis());
- String pckg = values.getAsString(Downloads.COLUMN_NOTIFICATION_PACKAGE);
- String clazz = values.getAsString(Downloads.COLUMN_NOTIFICATION_CLASS);
+ copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues);
+ filteredValues.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING);
+ filteredValues.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, System.currentTimeMillis());
+ String pckg = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
+ String clazz = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
if (pckg != null && clazz != null) {
int uid = Binder.getCallingUid();
try {
if (uid == 0 ||
getContext().getPackageManager().getApplicationInfo(pckg, 0).uid == uid) {
- filteredValues.put(Downloads.COLUMN_NOTIFICATION_PACKAGE, pckg);
- filteredValues.put(Downloads.COLUMN_NOTIFICATION_CLASS, clazz);
+ filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, pckg);
+ filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_CLASS, clazz);
}
} catch (PackageManager.NameNotFoundException ex) {
/* ignored for now */
}
}
- copyString(Downloads.COLUMN_NOTIFICATION_EXTRAS, values, filteredValues);
- copyString(Downloads.COLUMN_COOKIE_DATA, values, filteredValues);
- copyString(Downloads.COLUMN_USER_AGENT, values, filteredValues);
- copyString(Downloads.COLUMN_REFERER, values, filteredValues);
- if (getContext().checkCallingPermission(Downloads.PERMISSION_ACCESS_ADVANCED)
+ copyString(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_COOKIE_DATA, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_USER_AGENT, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_REFERER, values, filteredValues);
+ if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED)
== PackageManager.PERMISSION_GRANTED) {
- copyInteger(Downloads.COLUMN_OTHER_UID, values, filteredValues);
+ copyInteger(Downloads.Impl.COLUMN_OTHER_UID, values, filteredValues);
}
filteredValues.put(Constants.UID, Binder.getCallingUid());
if (Binder.getCallingUid() == 0) {
copyInteger(Constants.UID, values, filteredValues);
}
- copyString(Downloads.COLUMN_TITLE, values, filteredValues);
- copyString(Downloads.COLUMN_DESCRIPTION, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues);
if (Constants.LOGVV) {
Log.v(Constants.TAG, "initiating download with UID "
+ filteredValues.getAsInteger(Constants.UID));
- if (filteredValues.containsKey(Downloads.COLUMN_OTHER_UID)) {
+ if (filteredValues.containsKey(Downloads.Impl.COLUMN_OTHER_UID)) {
Log.v(Constants.TAG, "other UID " +
- filteredValues.getAsInteger(Downloads.COLUMN_OTHER_UID));
+ filteredValues.getAsInteger(Downloads.Impl.COLUMN_OTHER_UID));
}
}
@@ -339,7 +361,7 @@ public final class DownloadProvider extends ContentProvider {
if (rowID != -1) {
context.startService(new Intent(context, DownloadService.class));
- ret = Uri.parse(Downloads.CONTENT_URI + "/" + rowID);
+ ret = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + rowID);
context.getContentResolver().notifyChange(uri, null);
} else {
if (Config.LOGD) {
@@ -373,7 +395,7 @@ public final class DownloadProvider extends ContentProvider {
}
case DOWNLOADS_ID: {
qb.setTables(DB_TABLE);
- qb.appendWhere(Downloads._ID + "=");
+ qb.appendWhere(Downloads.Impl._ID + "=");
qb.appendWhere(uri.getPathSegments().get(1));
emptyWhere = false;
break;
@@ -386,25 +408,45 @@ public final class DownloadProvider extends ContentProvider {
}
}
- if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0 &&
+ int callingUid = Binder.getCallingUid();
+ if (Binder.getCallingPid() != Process.myPid() &&
+ callingUid != mSystemUid &&
+ callingUid != mDefContainerUid &&
Process.supportsProcesses()) {
- if (!emptyWhere) {
- qb.appendWhere(" AND ");
- }
- qb.appendWhere("( " + Constants.UID + "=" + Binder.getCallingUid() + " OR "
- + Downloads.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )");
- emptyWhere = false;
-
+ boolean canSeeAllExternal;
if (projection == null) {
projection = sAppReadableColumnsArray;
+ // sAppReadableColumnsArray includes _DATA, which is not allowed
+ // to be seen except by the initiating application
+ canSeeAllExternal = false;
} else {
+ canSeeAllExternal = getContext().checkCallingPermission(
+ Downloads.Impl.PERMISSION_SEE_ALL_EXTERNAL)
+ == PackageManager.PERMISSION_GRANTED;
for (int i = 0; i < projection.length; ++i) {
if (!sAppReadableColumnsSet.contains(projection[i])) {
throw new IllegalArgumentException(
"column " + projection[i] + " is not allowed in queries");
}
+ canSeeAllExternal = canSeeAllExternal
+ && !projection[i].equals(Downloads.Impl._DATA);
}
}
+ if (!emptyWhere) {
+ qb.appendWhere(" AND ");
+ emptyWhere = false;
+ }
+ String validUid = "( " + Constants.UID + "="
+ + Binder.getCallingUid() + " OR "
+ + Downloads.Impl.COLUMN_OTHER_UID + "="
+ + Binder.getCallingUid() + " )";
+ if (canSeeAllExternal) {
+ qb.appendWhere("( " + validUid + " OR "
+ + Downloads.Impl.DESTINATION_EXTERNAL + " = "
+ + Downloads.Impl.COLUMN_DESTINATION + " )");
+ } else {
+ qb.appendWhere(validUid);
+ }
}
if (Constants.LOGVV) {
@@ -489,18 +531,28 @@ public final class DownloadProvider extends ContentProvider {
ContentValues filteredValues;
if (Binder.getCallingPid() != Process.myPid()) {
filteredValues = new ContentValues();
- copyString(Downloads.COLUMN_APP_DATA, values, filteredValues);
- copyInteger(Downloads.COLUMN_VISIBILITY, values, filteredValues);
- Integer i = values.getAsInteger(Downloads.COLUMN_CONTROL);
+ copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues);
+ copyInteger(Downloads.Impl.COLUMN_VISIBILITY, values, filteredValues);
+ Integer i = values.getAsInteger(Downloads.Impl.COLUMN_CONTROL);
if (i != null) {
- filteredValues.put(Downloads.COLUMN_CONTROL, i);
+ filteredValues.put(Downloads.Impl.COLUMN_CONTROL, i);
startService = true;
}
- copyInteger(Downloads.COLUMN_CONTROL, values, filteredValues);
- copyString(Downloads.COLUMN_TITLE, values, filteredValues);
- copyString(Downloads.COLUMN_DESCRIPTION, values, filteredValues);
+ copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues);
+ copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues);
} else {
filteredValues = values;
+ String filename = values.getAsString(Downloads.Impl._DATA);
+ if (filename != null) {
+ Cursor c = query(uri, new String[]
+ { Downloads.Impl.COLUMN_TITLE }, null, null, null);
+ if (!c.moveToFirst() || c.getString(0) == null) {
+ values.put(Downloads.Impl.COLUMN_TITLE,
+ new File(filename).getName());
+ }
+ c.close();
+ }
}
int match = sURIMatcher.match(uri);
switch (match) {
@@ -519,11 +571,14 @@ public final class DownloadProvider extends ContentProvider {
if (match == DOWNLOADS_ID) {
String segment = uri.getPathSegments().get(1);
rowId = Long.parseLong(segment);
- myWhere += " ( " + Downloads._ID + " = " + rowId + " ) ";
+ myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) ";
}
- if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0) {
+ int callingUid = Binder.getCallingUid();
+ if (Binder.getCallingPid() != Process.myPid() &&
+ callingUid != mSystemUid &&
+ callingUid != mDefContainerUid) {
myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR "
- + Downloads.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )";
+ + Downloads.Impl.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )";
}
if (filteredValues.size() > 0) {
count = db.update(DB_TABLE, filteredValues, myWhere, whereArgs);
@@ -575,11 +630,15 @@ public final class DownloadProvider extends ContentProvider {
if (match == DOWNLOADS_ID) {
String segment = uri.getPathSegments().get(1);
long rowId = Long.parseLong(segment);
- myWhere += " ( " + Downloads._ID + " = " + rowId + " ) ";
+ myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) ";
}
- if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0) {
+ int callingUid = Binder.getCallingUid();
+ if (Binder.getCallingPid() != Process.myPid() &&
+ callingUid != mSystemUid &&
+ callingUid != mDefContainerUid) {
myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR "
- + Downloads.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )";
+ + Downloads.Impl.COLUMN_OTHER_UID + "="
+ + Binder.getCallingUid() + " )";
}
count = db.delete(DB_TABLE, myWhere, whereArgs);
break;
@@ -604,7 +663,8 @@ public final class DownloadProvider extends ContentProvider {
if (Constants.LOGVV) {
Log.v(Constants.TAG, "openFile uri: " + uri + ", mode: " + mode
+ ", uid: " + Binder.getCallingUid());
- Cursor cursor = query(Downloads.CONTENT_URI, new String[] { "_id" }, null, null, "_id");
+ Cursor cursor = query(Downloads.Impl.CONTENT_URI,
+ new String[] { "_id" }, null, null, "_id");
if (cursor == null) {
Log.v(Constants.TAG, "null cursor in openFile");
} else {
@@ -673,7 +733,7 @@ public final class DownloadProvider extends ContentProvider {
throw new FileNotFoundException("couldn't open file");
} else {
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_LAST_MODIFICATION, System.currentTimeMillis());
+ values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, System.currentTimeMillis());
update(uri, values, null, null);
}
return ret;
diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java
index 2065c649..e8f10e7d 100644
--- a/src/com/android/providers/downloads/DownloadReceiver.java
+++ b/src/com/android/providers/downloads/DownloadReceiver.java
@@ -86,22 +86,23 @@ public class DownloadReceiver extends BroadcastReceiver {
intent.getData(), null, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
- int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS);
+ int statusColumn = cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
int status = cursor.getInt(statusColumn);
int visibilityColumn =
- cursor.getColumnIndexOrThrow(Downloads.COLUMN_VISIBILITY);
+ cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_VISIBILITY);
int visibility = cursor.getInt(visibilityColumn);
- if (Downloads.isStatusCompleted(status)
- && visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
+ if (Downloads.Impl.isStatusCompleted(status)
+ && visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_VISIBLE);
+ values.put(Downloads.Impl.COLUMN_VISIBILITY,
+ Downloads.Impl.VISIBILITY_VISIBLE);
context.getContentResolver().update(intent.getData(), values, null, null);
}
if (intent.getAction().equals(Constants.ACTION_OPEN)) {
- int filenameColumn = cursor.getColumnIndexOrThrow(Downloads._DATA);
+ int filenameColumn = cursor.getColumnIndexOrThrow(Downloads.Impl._DATA);
int mimetypeColumn =
- cursor.getColumnIndexOrThrow(Downloads.COLUMN_MIME_TYPE);
+ cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_MIME_TYPE);
String filename = cursor.getString(filenameColumn);
String mimetype = cursor.getString(mimetypeColumn);
Uri path = Uri.parse(filename);
@@ -122,17 +123,18 @@ public class DownloadReceiver extends BroadcastReceiver {
// swallow the exception entirely
}
} else {
- int packageColumn =
- cursor.getColumnIndexOrThrow(Downloads.COLUMN_NOTIFICATION_PACKAGE);
- int classColumn =
- cursor.getColumnIndexOrThrow(Downloads.COLUMN_NOTIFICATION_CLASS);
+ int packageColumn = cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
+ int classColumn = cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
String pckg = cursor.getString(packageColumn);
String clazz = cursor.getString(classColumn);
if (pckg != null && clazz != null) {
- Intent appIntent = new Intent(Downloads.ACTION_NOTIFICATION_CLICKED);
+ Intent appIntent =
+ new Intent(Downloads.Impl.ACTION_NOTIFICATION_CLICKED);
appIntent.setClassName(pckg, clazz);
if (intent.getBooleanExtra("multiple", true)) {
- appIntent.setData(Downloads.CONTENT_URI);
+ appIntent.setData(Downloads.Impl.CONTENT_URI);
} else {
appIntent.setData(intent.getData());
}
@@ -155,15 +157,16 @@ public class DownloadReceiver extends BroadcastReceiver {
intent.getData(), null, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
- int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS);
+ int statusColumn = cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
int status = cursor.getInt(statusColumn);
int visibilityColumn =
- cursor.getColumnIndexOrThrow(Downloads.COLUMN_VISIBILITY);
+ cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_VISIBILITY);
int visibility = cursor.getInt(visibilityColumn);
- if (Downloads.isStatusCompleted(status)
- && visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
+ if (Downloads.Impl.isStatusCompleted(status)
+ && visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_VISIBLE);
+ values.put(Downloads.Impl.COLUMN_VISIBILITY,
+ Downloads.Impl.VISIBILITY_VISIBLE);
context.getContentResolver().update(intent.getData(), values, null, null);
}
}
diff --git a/src/com/android/providers/downloads/DownloadService.java b/src/com/android/providers/downloads/DownloadService.java
index a246d29f..9e890ea0 100644
--- a/src/com/android/providers/downloads/DownloadService.java
+++ b/src/com/android/providers/downloads/DownloadService.java
@@ -203,7 +203,7 @@ public class DownloadService extends Service {
mDownloads = Lists.newArrayList();
mObserver = new DownloadManagerContentObserver();
- getContentResolver().registerContentObserver(Downloads.CONTENT_URI,
+ getContentResolver().registerContentObserver(Downloads.Impl.CONTENT_URI,
true, mObserver);
mMediaScannerService = null;
@@ -307,8 +307,8 @@ public class DownloadService extends Service {
boolean networkRoaming = Helpers.isNetworkRoaming(DownloadService.this);
long now = System.currentTimeMillis();
- Cursor cursor = getContentResolver().query(Downloads.CONTENT_URI,
- null, null, null, Downloads._ID);
+ Cursor cursor = getContentResolver().query(Downloads.Impl.CONTENT_URI,
+ null, null, null, Downloads.Impl._ID);
if (cursor == null) {
// TODO: this doesn't look right, it'd leave the loop in an inconsistent state
@@ -325,7 +325,7 @@ public class DownloadService extends Service {
boolean isAfterLast = cursor.isAfterLast();
- int idColumn = cursor.getColumnIndexOrThrow(Downloads._ID);
+ int idColumn = cursor.getColumnIndexOrThrow(Downloads.Impl._ID);
/*
* Walk the cursor and the local array to keep them in sync. The key
@@ -491,8 +491,8 @@ public class DownloadService extends Service {
fileSet.add(files[i].getPath());
}
- Cursor cursor = getContentResolver().query(Downloads.CONTENT_URI,
- new String[] { Downloads._DATA }, null, null, null);
+ Cursor cursor = getContentResolver().query(Downloads.Impl.CONTENT_URI,
+ new String[] { Downloads.Impl._DATA }, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
@@ -515,10 +515,10 @@ public class DownloadService extends Service {
* Drops old rows from the database to prevent it from growing too large
*/
private void trimDatabase() {
- Cursor cursor = getContentResolver().query(Downloads.CONTENT_URI,
- new String[] { Downloads._ID },
- Downloads.COLUMN_STATUS + " >= '200'", null,
- Downloads.COLUMN_LAST_MODIFICATION);
+ Cursor cursor = getContentResolver().query(Downloads.Impl.CONTENT_URI,
+ new String[] { Downloads.Impl._ID },
+ Downloads.Impl.COLUMN_STATUS + " >= '200'", null,
+ Downloads.Impl.COLUMN_LAST_MODIFICATION);
if (cursor == null) {
// This isn't good - if we can't do basic queries in our database, nothing's gonna work
Log.e(Constants.TAG, "null cursor in trimDatabase");
@@ -526,11 +526,11 @@ public class DownloadService extends Service {
}
if (cursor.moveToFirst()) {
int numDelete = cursor.getCount() - Constants.MAX_DOWNLOADS;
- int columnId = cursor.getColumnIndexOrThrow(Downloads._ID);
+ int columnId = cursor.getColumnIndexOrThrow(Downloads.Impl._ID);
while (numDelete > 0) {
getContentResolver().delete(
- ContentUris.withAppendedId(Downloads.CONTENT_URI, cursor.getLong(columnId)),
- null, null);
+ ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI,
+ cursor.getLong(columnId)), null, null);
if (!cursor.moveToNext()) {
break;
}
@@ -547,35 +547,39 @@ public class DownloadService extends Service {
private void insertDownload(
Cursor cursor, int arrayPos,
boolean networkAvailable, boolean networkRoaming, long now) {
- int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS);
+ int statusColumn = cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
int failedColumn = cursor.getColumnIndexOrThrow(Constants.FAILED_CONNECTIONS);
int retryRedirect =
cursor.getInt(cursor.getColumnIndexOrThrow(Constants.RETRY_AFTER_X_REDIRECT_COUNT));
DownloadInfo info = new DownloadInfo(
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads._ID)),
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COLUMN_URI)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_NO_INTEGRITY)) == 1,
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COLUMN_FILE_NAME_HINT)),
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads._DATA)),
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COLUMN_MIME_TYPE)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_DESTINATION)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_VISIBILITY)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_CONTROL)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl._ID)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_URI)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_NO_INTEGRITY)) == 1,
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_FILE_NAME_HINT)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl._DATA)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_MIME_TYPE)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESTINATION)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_VISIBILITY)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_CONTROL)),
cursor.getInt(statusColumn),
cursor.getInt(failedColumn),
retryRedirect & 0xfffffff,
retryRedirect >> 28,
- cursor.getLong(cursor.getColumnIndexOrThrow(Downloads.COLUMN_LAST_MODIFICATION)),
+ cursor.getLong(cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_LAST_MODIFICATION)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE)),
cursor.getString(cursor.getColumnIndexOrThrow(
- Downloads.COLUMN_NOTIFICATION_PACKAGE)),
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COLUMN_NOTIFICATION_CLASS)),
+ Downloads.Impl.COLUMN_NOTIFICATION_CLASS)),
cursor.getString(cursor.getColumnIndexOrThrow(
- Downloads.COLUMN_NOTIFICATION_EXTRAS)),
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COLUMN_COOKIE_DATA)),
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COLUMN_USER_AGENT)),
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COLUMN_REFERER)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_TOTAL_BYTES)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_CURRENT_BYTES)),
+ Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_COOKIE_DATA)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_USER_AGENT)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_REFERER)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TOTAL_BYTES)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_CURRENT_BYTES)),
cursor.getString(cursor.getColumnIndexOrThrow(Constants.ETAG)),
cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) == 1);
@@ -609,36 +613,36 @@ public class DownloadService extends Service {
mDownloads.add(arrayPos, info);
if (info.mStatus == 0
- && (info.mDestination == Downloads.DESTINATION_EXTERNAL
- || info.mDestination == Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE)
+ && (info.mDestination == Downloads.Impl.DESTINATION_EXTERNAL
+ || info.mDestination == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE)
&& info.mMimeType != null
&& !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(info.mMimeType)) {
// Check to see if we are allowed to download this file. Only files
// that can be handled by the platform can be downloaded.
// special case DRM files, which we should always allow downloading.
Intent mimetypeIntent = new Intent(Intent.ACTION_VIEW);
-
+
// We can provide data as either content: or file: URIs,
// so allow both. (I think it would be nice if we just did
// everything as content: URIs)
// Actually, right now the download manager's UId restrictions
// prevent use from using content: so it's got to be file: or
// nothing
-
+
mimetypeIntent.setDataAndType(Uri.fromParts("file", "", null), info.mMimeType);
ResolveInfo ri = getPackageManager().resolveActivity(mimetypeIntent,
PackageManager.MATCH_DEFAULT_ONLY);
//Log.i(Constants.TAG, "*** QUERY " + mimetypeIntent + ": " + list);
-
+
if (ri == null) {
if (Config.LOGD) {
Log.d(Constants.TAG, "no application to handle MIME type " + info.mMimeType);
}
- info.mStatus = Downloads.STATUS_NOT_ACCEPTABLE;
+ info.mStatus = Downloads.Impl.STATUS_NOT_ACCEPTABLE;
- Uri uri = ContentUris.withAppendedId(Downloads.CONTENT_URI, info.mId);
+ Uri uri = ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, info.mId);
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_STATUS, Downloads.STATUS_NOT_ACCEPTABLE);
+ values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_NOT_ACCEPTABLE);
getContentResolver().update(uri, values, null, null);
info.sendIntentIfRequested(uri, this);
return;
@@ -654,12 +658,12 @@ public class DownloadService extends Service {
if (info.mHasActiveThread) {
throw new IllegalStateException("Multiple threads on same download on insert");
}
- if (info.mStatus != Downloads.STATUS_RUNNING) {
- info.mStatus = Downloads.STATUS_RUNNING;
+ if (info.mStatus != Downloads.Impl.STATUS_RUNNING) {
+ info.mStatus = Downloads.Impl.STATUS_RUNNING;
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_STATUS, info.mStatus);
+ values.put(Downloads.Impl.COLUMN_STATUS, info.mStatus);
getContentResolver().update(
- ContentUris.withAppendedId(Downloads.CONTENT_URI, info.mId),
+ ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, info.mId),
values, null, null);
}
DownloadThread downloader = new DownloadThread(this, info);
@@ -668,12 +672,12 @@ public class DownloadService extends Service {
}
} else {
if (info.mStatus == 0
- || info.mStatus == Downloads.STATUS_PENDING
- || info.mStatus == Downloads.STATUS_RUNNING) {
- info.mStatus = Downloads.STATUS_RUNNING_PAUSED;
- Uri uri = ContentUris.withAppendedId(Downloads.CONTENT_URI, info.mId);
+ || info.mStatus == Downloads.Impl.STATUS_PENDING
+ || info.mStatus == Downloads.Impl.STATUS_RUNNING) {
+ info.mStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
+ Uri uri = ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, info.mId);
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_STATUS, Downloads.STATUS_RUNNING_PAUSED);
+ values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_RUNNING_PAUSED);
getContentResolver().update(uri, values, null, null);
}
}
@@ -686,30 +690,32 @@ public class DownloadService extends Service {
Cursor cursor, int arrayPos,
boolean networkAvailable, boolean networkRoaming, long now) {
DownloadInfo info = (DownloadInfo) mDownloads.get(arrayPos);
- int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS);
+ int statusColumn = cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
int failedColumn = cursor.getColumnIndexOrThrow(Constants.FAILED_CONNECTIONS);
- info.mId = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads._ID));
- info.mUri = stringFromCursor(info.mUri, cursor, Downloads.COLUMN_URI);
- info.mNoIntegrity =
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_NO_INTEGRITY)) == 1;
- info.mHint = stringFromCursor(info.mHint, cursor, Downloads.COLUMN_FILE_NAME_HINT);
- info.mFileName = stringFromCursor(info.mFileName, cursor, Downloads._DATA);
- info.mMimeType = stringFromCursor(info.mMimeType, cursor, Downloads.COLUMN_MIME_TYPE);
+ info.mId = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl._ID));
+ info.mUri = stringFromCursor(info.mUri, cursor, Downloads.Impl.COLUMN_URI);
+ info.mNoIntegrity = cursor.getInt(cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_NO_INTEGRITY)) == 1;
+ info.mHint = stringFromCursor(info.mHint, cursor, Downloads.Impl.COLUMN_FILE_NAME_HINT);
+ info.mFileName = stringFromCursor(info.mFileName, cursor, Downloads.Impl._DATA);
+ info.mMimeType = stringFromCursor(info.mMimeType, cursor, Downloads.Impl.COLUMN_MIME_TYPE);
info.mDestination = cursor.getInt(cursor.getColumnIndexOrThrow(
- Downloads.COLUMN_DESTINATION));
+ Downloads.Impl.COLUMN_DESTINATION));
int newVisibility = cursor.getInt(cursor.getColumnIndexOrThrow(
- Downloads.COLUMN_VISIBILITY));
- if (info.mVisibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
- && newVisibility != Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
- && Downloads.isStatusCompleted(info.mStatus)) {
+ Downloads.Impl.COLUMN_VISIBILITY));
+ if (info.mVisibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
+ && newVisibility != Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
+ && Downloads.Impl.isStatusCompleted(info.mStatus)) {
mNotifier.mNotificationMgr.cancel(info.mId);
}
info.mVisibility = newVisibility;
synchronized (info) {
- info.mControl = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_CONTROL));
+ info.mControl = cursor.getInt(cursor.getColumnIndexOrThrow(
+ Downloads.Impl.COLUMN_CONTROL));
}
int newStatus = cursor.getInt(statusColumn);
- if (!Downloads.isStatusCompleted(info.mStatus) && Downloads.isStatusCompleted(newStatus)) {
+ if (!Downloads.Impl.isStatusCompleted(info.mStatus) &&
+ Downloads.Impl.isStatusCompleted(newStatus)) {
mNotifier.mNotificationMgr.cancel(info.mId);
}
info.mStatus = newStatus;
@@ -719,17 +725,19 @@ public class DownloadService extends Service {
info.mRetryAfter = retryRedirect & 0xfffffff;
info.mRedirectCount = retryRedirect >> 28;
info.mLastMod = cursor.getLong(cursor.getColumnIndexOrThrow(
- Downloads.COLUMN_LAST_MODIFICATION));
+ Downloads.Impl.COLUMN_LAST_MODIFICATION));
info.mPackage = stringFromCursor(
- info.mPackage, cursor, Downloads.COLUMN_NOTIFICATION_PACKAGE);
- info.mClass = stringFromCursor(info.mClass, cursor, Downloads.COLUMN_NOTIFICATION_CLASS);
- info.mCookies = stringFromCursor(info.mCookies, cursor, Downloads.COLUMN_COOKIE_DATA);
- info.mUserAgent = stringFromCursor(info.mUserAgent, cursor, Downloads.COLUMN_USER_AGENT);
- info.mReferer = stringFromCursor(info.mReferer, cursor, Downloads.COLUMN_REFERER);
+ info.mPackage, cursor, Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
+ info.mClass = stringFromCursor(
+ info.mClass, cursor, Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
+ info.mCookies = stringFromCursor(info.mCookies, cursor, Downloads.Impl.COLUMN_COOKIE_DATA);
+ info.mUserAgent = stringFromCursor(
+ info.mUserAgent, cursor, Downloads.Impl.COLUMN_USER_AGENT);
+ info.mReferer = stringFromCursor(info.mReferer, cursor, Downloads.Impl.COLUMN_REFERER);
info.mTotalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(
- Downloads.COLUMN_TOTAL_BYTES));
+ Downloads.Impl.COLUMN_TOTAL_BYTES));
info.mCurrentBytes = cursor.getInt(cursor.getColumnIndexOrThrow(
- Downloads.COLUMN_CURRENT_BYTES));
+ Downloads.Impl.COLUMN_CURRENT_BYTES));
info.mETag = stringFromCursor(info.mETag, cursor, Constants.ETAG);
info.mMediaScanned =
cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) == 1;
@@ -743,11 +751,11 @@ public class DownloadService extends Service {
if (info.mHasActiveThread) {
throw new IllegalStateException("Multiple threads on same download on update");
}
- info.mStatus = Downloads.STATUS_RUNNING;
+ info.mStatus = Downloads.Impl.STATUS_RUNNING;
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_STATUS, info.mStatus);
+ values.put(Downloads.Impl.COLUMN_STATUS, info.mStatus);
getContentResolver().update(
- ContentUris.withAppendedId(Downloads.CONTENT_URI, info.mId),
+ ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, info.mId),
values, null, null);
DownloadThread downloader = new DownloadThread(this, info);
info.mHasActiveThread = true;
@@ -792,9 +800,10 @@ public class DownloadService extends Service {
*/
private void deleteDownload(int arrayPos) {
DownloadInfo info = (DownloadInfo) mDownloads.get(arrayPos);
- if (info.mStatus == Downloads.STATUS_RUNNING) {
- info.mStatus = Downloads.STATUS_CANCELED;
- } else if (info.mDestination != Downloads.DESTINATION_EXTERNAL && info.mFileName != null) {
+ if (info.mStatus == Downloads.Impl.STATUS_RUNNING) {
+ info.mStatus = Downloads.Impl.STATUS_CANCELED;
+ } else if (info.mDestination != Downloads.Impl.DESTINATION_EXTERNAL
+ && info.mFileName != null) {
new File(info.mFileName).delete();
}
mNotifier.mNotificationMgr.cancel(info.mId);
@@ -811,10 +820,10 @@ public class DownloadService extends Service {
*/
private long nextAction(int arrayPos, long now) {
DownloadInfo info = (DownloadInfo) mDownloads.get(arrayPos);
- if (Downloads.isStatusCompleted(info.mStatus)) {
+ if (Downloads.Impl.isStatusCompleted(info.mStatus)) {
return -1;
}
- if (info.mStatus != Downloads.STATUS_RUNNING_PAUSED) {
+ if (info.mStatus != Downloads.Impl.STATUS_RUNNING_PAUSED) {
return 0;
}
if (info.mNumFailed == 0) {
@@ -841,8 +850,8 @@ public class DownloadService extends Service {
private boolean shouldScanFile(int arrayPos) {
DownloadInfo info = (DownloadInfo) mDownloads.get(arrayPos);
return !info.mMediaScanned
- && info.mDestination == Downloads.DESTINATION_EXTERNAL
- && Downloads.isStatusSuccess(info.mStatus)
+ && info.mDestination == Downloads.Impl.DESTINATION_EXTERNAL
+ && Downloads.Impl.isStatusSuccess(info.mStatus)
&& !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(info.mMimeType);
}
@@ -869,9 +878,9 @@ public class DownloadService extends Service {
if (cursor != null) {
ContentValues values = new ContentValues();
values.put(Constants.MEDIA_SCANNED, 1);
- getContentResolver().update(
- ContentUris.withAppendedId(Downloads.CONTENT_URI,
- cursor.getLong(cursor.getColumnIndexOrThrow(Downloads._ID))),
+ getContentResolver().update(ContentUris.withAppendedId(
+ Downloads.Impl.CONTENT_URI, cursor.getLong(
+ cursor.getColumnIndexOrThrow(Downloads.Impl._ID))),
values, null, null);
}
return true;
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index 1ad1d4f9..d2bd3220 100644
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -37,6 +37,7 @@ import android.provider.DrmStore;
import android.util.Config;
import android.util.Log;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
@@ -80,7 +81,7 @@ public class DownloadThread extends Thread {
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- int finalStatus = Downloads.STATUS_UNKNOWN_ERROR;
+ int finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;
boolean countRetry = false;
int retryAfter = 0;
int redirectCount = mInfo.mRedirectCount;
@@ -91,7 +92,7 @@ public class DownloadThread extends Thread {
FileOutputStream stream = null;
AndroidHttpClient client = null;
PowerManager.WakeLock wakeLock = null;
- Uri contentUri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.mId);
+ Uri contentUri = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + mInfo.mId);
try {
boolean continuingDownload = false;
@@ -113,7 +114,7 @@ public class DownloadThread extends Thread {
filename = mInfo.mFileName;
if (filename != null) {
if (!Helpers.isFilenameValid(filename)) {
- finalStatus = Downloads.STATUS_FILE_ERROR;
+ finalStatus = Downloads.Impl.STATUS_FILE_ERROR;
notifyDownloadCompleted(
finalStatus, false, 0, 0, false, filename, null, mInfo.mMimeType);
return;
@@ -133,7 +134,7 @@ public class DownloadThread extends Thread {
"can't resume interrupted non-resumable download");
}
f.delete();
- finalStatus = Downloads.STATUS_PRECONDITION_FAILED;
+ finalStatus = Downloads.Impl.STATUS_PRECONDITION_FAILED;
notifyDownloadCompleted(
finalStatus, false, 0, 0, false, filename, null, mInfo.mMimeType);
return;
@@ -155,9 +156,9 @@ public class DownloadThread extends Thread {
// progress to the database
long timeLastNotification = 0;
- client = AndroidHttpClient.newInstance(userAgent());
+ client = AndroidHttpClient.newInstance(userAgent(), mContext);
- if (stream != null && mInfo.mDestination == Downloads.DESTINATION_EXTERNAL
+ if (stream != null && mInfo.mDestination == Downloads.Impl.DESTINATION_EXTERNAL
&& !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING
.equalsIgnoreCase(mimeType)) {
try {
@@ -210,7 +211,7 @@ http_request_loop:
Log.d(Constants.TAG, "Arg exception trying to execute request for " +
mInfo.mId + " : " + ex);
}
- finalStatus = Downloads.STATUS_BAD_REQUEST;
+ finalStatus = Downloads.Impl.STATUS_BAD_REQUEST;
request.abort();
break http_request_loop;
} catch (IOException ex) {
@@ -222,9 +223,9 @@ http_request_loop:
}
}
if (!Helpers.isNetworkAvailable(mContext)) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
} else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
@@ -234,7 +235,7 @@ http_request_loop:
Log.d(Constants.TAG, "IOException trying to execute request for " +
mInfo.mId + " : " + ex);
}
- finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
+ finalStatus = Downloads.Impl.STATUS_HTTP_DATA_ERROR;
}
request.abort();
break http_request_loop;
@@ -245,7 +246,7 @@ http_request_loop:
if (Constants.LOGVV) {
Log.v(Constants.TAG, "got HTTP response code 503");
}
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
countRetry = true;
Header header = response.getFirstHeader("Retry-After");
if (header != null) {
@@ -286,7 +287,7 @@ http_request_loop:
} else if (Config.LOGD) {
Log.d(Constants.TAG, "too many redirects for download " + mInfo.mId);
}
- finalStatus = Downloads.STATUS_TOO_MANY_REDIRECTS;
+ finalStatus = Downloads.Impl.STATUS_TOO_MANY_REDIRECTS;
request.abort();
break http_request_loop;
}
@@ -311,17 +312,17 @@ http_request_loop:
"Couldn't resolve redirect URI for download " +
mInfo.mId);
}
- finalStatus = Downloads.STATUS_BAD_REQUEST;
+ finalStatus = Downloads.Impl.STATUS_BAD_REQUEST;
request.abort();
break http_request_loop;
}
++redirectCount;
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
request.abort();
break http_request_loop;
}
}
- if ((!continuingDownload && statusCode != Downloads.STATUS_SUCCESS)
+ if ((!continuingDownload && statusCode != Downloads.Impl.STATUS_SUCCESS)
|| (continuingDownload && statusCode != 206)) {
if (Constants.LOGV) {
Log.d(Constants.TAG, "http error " + statusCode + " for " + mInfo.mUri);
@@ -329,14 +330,14 @@ http_request_loop:
Log.d(Constants.TAG, "http error " + statusCode + " for download " +
mInfo.mId);
}
- if (Downloads.isStatusError(statusCode)) {
+ if (Downloads.Impl.isStatusError(statusCode)) {
finalStatus = statusCode;
} else if (statusCode >= 300 && statusCode < 400) {
- finalStatus = Downloads.STATUS_UNHANDLED_REDIRECT;
- } else if (continuingDownload && statusCode == Downloads.STATUS_SUCCESS) {
- finalStatus = Downloads.STATUS_PRECONDITION_FAILED;
+ finalStatus = Downloads.Impl.STATUS_UNHANDLED_REDIRECT;
+ } else if (continuingDownload && statusCode == Downloads.Impl.STATUS_SUCCESS) {
+ finalStatus = Downloads.Impl.STATUS_PRECONDITION_FAILED;
} else {
- finalStatus = Downloads.STATUS_UNHANDLED_HTTP_CODE;
+ finalStatus = Downloads.Impl.STATUS_UNHANDLED_HTTP_CODE;
}
request.abort();
break http_request_loop;
@@ -403,7 +404,7 @@ http_request_loop:
if (Config.LOGD) {
Log.d(Constants.TAG, "can't know size of download, giving up");
}
- finalStatus = Downloads.STATUS_LENGTH_REQUIRED;
+ finalStatus = Downloads.Impl.STATUS_LENGTH_REQUIRED;
request.abort();
break http_request_loop;
}
@@ -430,18 +431,18 @@ http_request_loop:
}
ContentValues values = new ContentValues();
- values.put(Downloads._DATA, filename);
+ values.put(Downloads.Impl._DATA, filename);
if (headerETag != null) {
values.put(Constants.ETAG, headerETag);
}
if (mimeType != null) {
- values.put(Downloads.COLUMN_MIME_TYPE, mimeType);
+ values.put(Downloads.Impl.COLUMN_MIME_TYPE, mimeType);
}
int contentLength = -1;
if (headerContentLength != null) {
contentLength = Integer.parseInt(headerContentLength);
}
- values.put(Downloads.COLUMN_TOTAL_BYTES, contentLength);
+ values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, contentLength);
mContext.getContentResolver().update(contentUri, values, null, null);
}
@@ -457,9 +458,9 @@ http_request_loop:
}
}
if (!Helpers.isNetworkAvailable(mContext)) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
} else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
@@ -472,7 +473,7 @@ http_request_loop:
Log.d(Constants.TAG, "IOException getting entity for download " +
mInfo.mId + " : " + ex);
}
- finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
+ finalStatus = Downloads.Impl.STATUS_HTTP_DATA_ERROR;
}
request.abort();
break http_request_loop;
@@ -490,7 +491,7 @@ http_request_loop:
}
}
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar);
+ values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, bytesSoFar);
mContext.getContentResolver().update(contentUri, values, null, null);
if (!mInfo.mNoIntegrity && headerETag == null) {
if (Constants.LOGV) {
@@ -504,11 +505,11 @@ http_request_loop:
Log.d(Constants.TAG,
"can't resume interrupted download with no ETag");
}
- finalStatus = Downloads.STATUS_PRECONDITION_FAILED;
+ finalStatus = Downloads.Impl.STATUS_PRECONDITION_FAILED;
} else if (!Helpers.isNetworkAvailable(mContext)) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
} else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
@@ -518,16 +519,16 @@ http_request_loop:
Log.d(Constants.TAG, "download IOException for download " +
mInfo.mId + " : " + ex);
}
- finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
+ finalStatus = Downloads.Impl.STATUS_HTTP_DATA_ERROR;
}
request.abort();
break http_request_loop;
}
if (bytesRead == -1) { // success
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar);
+ values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, bytesSoFar);
if (headerContentLength == null) {
- values.put(Downloads.COLUMN_TOTAL_BYTES, bytesSoFar);
+ values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, bytesSoFar);
}
mContext.getContentResolver().update(contentUri, values, null, null);
if ((headerContentLength != null)
@@ -541,11 +542,11 @@ http_request_loop:
Log.d(Constants.TAG, "mismatched content length for " +
mInfo.mId);
}
- finalStatus = Downloads.STATUS_LENGTH_REQUIRED;
+ finalStatus = Downloads.Impl.STATUS_LENGTH_REQUIRED;
} else if (!Helpers.isNetworkAvailable(mContext)) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
} else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
@@ -554,7 +555,7 @@ http_request_loop:
Log.d(Constants.TAG, "closed socket for download " +
mInfo.mId);
}
- finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
+ finalStatus = Downloads.Impl.STATUS_HTTP_DATA_ERROR;
}
break http_request_loop;
}
@@ -567,7 +568,7 @@ http_request_loop:
stream = new FileOutputStream(filename, true);
}
stream.write(data, 0, bytesRead);
- if (mInfo.mDestination == Downloads.DESTINATION_EXTERNAL
+ if (mInfo.mDestination == Downloads.Impl.DESTINATION_EXTERNAL
&& !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING
.equalsIgnoreCase(mimeType)) {
try {
@@ -586,7 +587,7 @@ http_request_loop:
} catch (IOException ex) {
if (!Helpers.discardPurgeableFiles(
mContext, Constants.BUFFER_SIZE)) {
- finalStatus = Downloads.STATUS_FILE_ERROR;
+ finalStatus = Downloads.Impl.STATUS_FILE_ERROR;
break http_request_loop;
}
}
@@ -597,7 +598,7 @@ http_request_loop:
&& now - timeLastNotification
> Constants.MIN_PROGRESS_TIME) {
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar);
+ values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, bytesSoFar);
mContext.getContentResolver().update(
contentUri, values, null, null);
bytesNotified = bytesSoFar;
@@ -608,29 +609,29 @@ http_request_loop:
Log.v(Constants.TAG, "downloaded " + bytesSoFar + " for " + mInfo.mUri);
}
synchronized (mInfo) {
- if (mInfo.mControl == Downloads.CONTROL_PAUSED) {
+ if (mInfo.mControl == Downloads.Impl.CONTROL_PAUSED) {
if (Constants.LOGV) {
Log.v(Constants.TAG, "paused " + mInfo.mUri);
}
- finalStatus = Downloads.STATUS_RUNNING_PAUSED;
+ finalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED;
request.abort();
break http_request_loop;
}
}
- if (mInfo.mStatus == Downloads.STATUS_CANCELED) {
+ if (mInfo.mStatus == Downloads.Impl.STATUS_CANCELED) {
if (Constants.LOGV) {
Log.d(Constants.TAG, "canceled " + mInfo.mUri);
} else if (Config.LOGD) {
// Log.d(Constants.TAG, "canceled id " + mInfo.mId);
}
- finalStatus = Downloads.STATUS_CANCELED;
+ finalStatus = Downloads.Impl.STATUS_CANCELED;
break http_request_loop;
}
}
if (Constants.LOGV) {
Log.v(Constants.TAG, "download completed for " + mInfo.mUri);
}
- finalStatus = Downloads.STATUS_SUCCESS;
+ finalStatus = Downloads.Impl.STATUS_SUCCESS;
}
break;
}
@@ -638,7 +639,7 @@ http_request_loop:
if (Config.LOGD) {
Log.d(Constants.TAG, "FileNotFoundException for " + filename + " : " + ex);
}
- finalStatus = Downloads.STATUS_FILE_ERROR;
+ finalStatus = Downloads.Impl.STATUS_FILE_ERROR;
// falls through to the code that reports an error
} catch (RuntimeException ex) { //sometimes the socket code throws unchecked exceptions
if (Constants.LOGV) {
@@ -646,7 +647,7 @@ http_request_loop:
} else if (Config.LOGD) {
Log.d(Constants.TAG, "Exception for id " + mInfo.mId, ex);
}
- finalStatus = Downloads.STATUS_UNKNOWN_ERROR;
+ finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;
// falls through to the code that reports an error
} finally {
mInfo.mHasActiveThread = false;
@@ -671,10 +672,10 @@ http_request_loop:
}
if (filename != null) {
// if the download wasn't successful, delete the file
- if (Downloads.isStatusError(finalStatus)) {
+ if (Downloads.Impl.isStatusError(finalStatus)) {
new File(filename).delete();
filename = null;
- } else if (Downloads.isStatusSuccess(finalStatus) &&
+ } else if (Downloads.Impl.isStatusSuccess(finalStatus) &&
DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING
.equalsIgnoreCase(mimeType)) {
// transfer the file to the DRM content provider
@@ -682,14 +683,14 @@ http_request_loop:
Intent item = DrmStore.addDrmFile(mContext.getContentResolver(), file, null);
if (item == null) {
Log.w(Constants.TAG, "unable to add file " + filename + " to DrmProvider");
- finalStatus = Downloads.STATUS_UNKNOWN_ERROR;
+ finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;
} else {
filename = item.getDataString();
mimeType = item.getType();
}
file.delete();
- } else if (Downloads.isStatusSuccess(finalStatus)) {
+ } else if (Downloads.Impl.isStatusSuccess(finalStatus)) {
// make sure the file is readable
FileUtils.setPermissions(filename, 0644, -1, -1);
@@ -732,7 +733,7 @@ http_request_loop:
String filename, String uri, String mimeType) {
notifyThroughDatabase(
status, countRetry, retryAfter, redirectCount, gotData, filename, uri, mimeType);
- if (Downloads.isStatusCompleted(status)) {
+ if (Downloads.Impl.isStatusCompleted(status)) {
notifyThroughIntent();
}
}
@@ -741,13 +742,13 @@ http_request_loop:
int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
String filename, String uri, String mimeType) {
ContentValues values = new ContentValues();
- values.put(Downloads.COLUMN_STATUS, status);
- values.put(Downloads._DATA, filename);
+ values.put(Downloads.Impl.COLUMN_STATUS, status);
+ values.put(Downloads.Impl._DATA, filename);
if (uri != null) {
- values.put(Downloads.COLUMN_URI, uri);
+ values.put(Downloads.Impl.COLUMN_URI, uri);
}
- values.put(Downloads.COLUMN_MIME_TYPE, mimeType);
- values.put(Downloads.COLUMN_LAST_MODIFICATION, System.currentTimeMillis());
+ values.put(Downloads.Impl.COLUMN_MIME_TYPE, mimeType);
+ values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, System.currentTimeMillis());
values.put(Constants.RETRY_AFTER_X_REDIRECT_COUNT, retryAfter + (redirectCount << 28));
if (!countRetry) {
values.put(Constants.FAILED_CONNECTIONS, 0);
@@ -757,8 +758,8 @@ http_request_loop:
values.put(Constants.FAILED_CONNECTIONS, mInfo.mNumFailed + 1);
}
- mContext.getContentResolver().update(
- ContentUris.withAppendedId(Downloads.CONTENT_URI, mInfo.mId), values, null, null);
+ mContext.getContentResolver().update(ContentUris.withAppendedId(
+ Downloads.Impl.CONTENT_URI, mInfo.mId), values, null, null);
}
/**
@@ -766,7 +767,7 @@ http_request_loop:
* download completed even if it's not actively watching the cursor.
*/
private void notifyThroughIntent() {
- Uri uri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.mId);
+ Uri uri = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + mInfo.mId);
mInfo.sendIntentIfRequested(uri, mContext);
}
diff --git a/src/com/android/providers/downloads/Helpers.java b/src/com/android/providers/downloads/Helpers.java
index d8f262c7..1e07d421 100644
--- a/src/com/android/providers/downloads/Helpers.java
+++ b/src/com/android/providers/downloads/Helpers.java
@@ -91,26 +91,26 @@ public class Helpers {
/*
* Don't download files that we won't be able to handle
*/
- if (destination == Downloads.DESTINATION_EXTERNAL
- || destination == Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE) {
+ if (destination == Downloads.Impl.DESTINATION_EXTERNAL
+ || destination == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE) {
if (mimeType == null) {
if (Config.LOGD) {
Log.d(Constants.TAG, "external download with no mime type not allowed");
}
- return new DownloadFileInfo(null, null, Downloads.STATUS_NOT_ACCEPTABLE);
+ return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_NOT_ACCEPTABLE);
}
if (!DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(mimeType)) {
// Check to see if we are allowed to download this file. Only files
// that can be handled by the platform can be downloaded.
// special case DRM files, which we should always allow downloading.
Intent intent = new Intent(Intent.ACTION_VIEW);
-
+
// We can provide data as either content: or file: URIs,
// so allow both. (I think it would be nice if we just did
// everything as content: URIs)
// Actually, right now the download manager's UId restrictions
// prevent use from using content: so it's got to be file: or
- // nothing
+ // nothing
PackageManager pm = context.getPackageManager();
intent.setDataAndType(Uri.fromParts("file", "", null), mimeType);
@@ -121,7 +121,7 @@ public class Helpers {
if (Config.LOGD) {
Log.d(Constants.TAG, "no handler found for type " + mimeType);
}
- return new DownloadFileInfo(null, null, Downloads.STATUS_NOT_ACCEPTABLE);
+ return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_NOT_ACCEPTABLE);
}
}
}
@@ -148,10 +148,11 @@ public class Helpers {
StatFs stat = null;
// DRM messages should be temporarily stored internally and then passed to
// the DRM content provider
- if (destination == Downloads.DESTINATION_CACHE_PARTITION
- || destination == Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE
- || destination == Downloads.DESTINATION_CACHE_PARTITION_NOROAMING
+ if (destination == Downloads.Impl.DESTINATION_CACHE_PARTITION
+ || destination == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE
+ || destination == Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING
|| DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(mimeType)) {
+ // Saving to internal storage.
base = Environment.getDownloadCacheDirectory();
stat = new StatFs(base.getPath());
@@ -160,52 +161,58 @@ public class Helpers {
* Put a bit of margin (in case creating the file grows the system by a few blocks).
*/
int blockSize = stat.getBlockSize();
- for (;;) {
- int availableBlocks = stat.getAvailableBlocks();
- if (blockSize * ((long) availableBlocks - 4) >= contentLength) {
- break;
- }
- if (!discardPurgeableFiles(context,
- contentLength - blockSize * ((long) availableBlocks - 4))) {
+ long bytesAvailable = blockSize * ((long) stat.getAvailableBlocks() - 4);
+ while (bytesAvailable < contentLength) {
+ // Insufficient space; try discarding purgeable files.
+ if (!discardPurgeableFiles(context, contentLength - bytesAvailable)) {
+ // No files to purge, give up.
if (Config.LOGD) {
Log.d(Constants.TAG,
"download aborted - not enough free space in internal storage");
}
- return new DownloadFileInfo(null, null, Downloads.STATUS_FILE_ERROR);
- }
- stat.restat(base.getPath());
- }
-
- } else {
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- String root = Environment.getExternalStorageDirectory().getPath();
- base = new File(root + Constants.DEFAULT_DL_SUBDIR);
- if (!base.isDirectory() && !base.mkdir()) {
- if (Config.LOGD) {
- Log.d(Constants.TAG, "download aborted - can't create base directory "
- + base.getPath());
- }
- return new DownloadFileInfo(null, null, Downloads.STATUS_FILE_ERROR);
- }
- stat = new StatFs(base.getPath());
- } else {
- if (Config.LOGD) {
- Log.d(Constants.TAG, "download aborted - no external storage");
+ return new DownloadFileInfo(null, null,
+ Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR);
+ } else {
+ // Recalculate available space and try again.
+ stat.restat(base.getPath());
+ bytesAvailable = blockSize * ((long) stat.getAvailableBlocks() - 4);
}
- return new DownloadFileInfo(null, null, Downloads.STATUS_FILE_ERROR);
}
+ } else if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ // Saving to external storage (SD card).
+ String root = Environment.getExternalStorageDirectory().getPath();
+ stat = new StatFs(root);
/*
* Check whether there's enough space on the target filesystem to save the file.
* Put a bit of margin (in case creating the file grows the system by a few blocks).
*/
if (stat.getBlockSize() * ((long) stat.getAvailableBlocks() - 4) < contentLength) {
+ // Insufficient space.
if (Config.LOGD) {
Log.d(Constants.TAG, "download aborted - not enough free space");
}
- return new DownloadFileInfo(null, null, Downloads.STATUS_FILE_ERROR);
+ return new DownloadFileInfo(null, null,
+ Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR);
}
+ base = new File(root + Constants.DEFAULT_DL_SUBDIR);
+ if (!base.isDirectory() && !base.mkdir()) {
+ // Can't create download directory, e.g. because a file called "download"
+ // already exists at the root level, or the SD card filesystem is read-only.
+ if (Config.LOGD) {
+ Log.d(Constants.TAG, "download aborted - can't create base directory "
+ + base.getPath());
+ }
+ return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_FILE_ERROR);
+ }
+ } else {
+ // No SD card found.
+ if (Config.LOGD) {
+ Log.d(Constants.TAG, "download aborted - no external storage");
+ }
+ return new DownloadFileInfo(null, null,
+ Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR);
}
boolean recoveryDir = Constants.RECOVERY_DIRECTORY.equalsIgnoreCase(filename + extension);
@@ -224,7 +231,7 @@ public class Helpers {
if (fullFilename != null) {
return new DownloadFileInfo(fullFilename, new FileOutputStream(fullFilename), 0);
} else {
- return new DownloadFileInfo(null, null, Downloads.STATUS_FILE_ERROR);
+ return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_FILE_ERROR);
}
}
@@ -380,9 +387,9 @@ public class Helpers {
String fullFilename = filename + extension;
if (!new File(fullFilename).exists()
&& (!recoveryDir ||
- (destination != Downloads.DESTINATION_CACHE_PARTITION &&
- destination != Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE &&
- destination != Downloads.DESTINATION_CACHE_PARTITION_NOROAMING))) {
+ (destination != Downloads.Impl.DESTINATION_CACHE_PARTITION &&
+ destination != Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE &&
+ destination != Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING))) {
return fullFilename;
}
filename = filename + Constants.FILENAME_SEQUENCE_SEPARATOR;
@@ -423,14 +430,14 @@ public class Helpers {
*/
public static final boolean discardPurgeableFiles(Context context, long targetBytes) {
Cursor cursor = context.getContentResolver().query(
- Downloads.CONTENT_URI,
+ Downloads.Impl.CONTENT_URI,
null,
"( " +
- Downloads.COLUMN_STATUS + " = '" + Downloads.STATUS_SUCCESS + "' AND " +
- Downloads.COLUMN_DESTINATION +
- " = '" + Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE + "' )",
+ Downloads.Impl.COLUMN_STATUS + " = '" + Downloads.Impl.STATUS_SUCCESS + "' AND " +
+ Downloads.Impl.COLUMN_DESTINATION +
+ " = '" + Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE + "' )",
null,
- Downloads.COLUMN_LAST_MODIFICATION);
+ Downloads.Impl.COLUMN_LAST_MODIFICATION);
if (cursor == null) {
return false;
}
@@ -438,16 +445,16 @@ public class Helpers {
try {
cursor.moveToFirst();
while (!cursor.isAfterLast() && totalFreed < targetBytes) {
- File file = new File(cursor.getString(cursor.getColumnIndex(Downloads._DATA)));
+ File file = new File(cursor.getString(cursor.getColumnIndex(Downloads.Impl._DATA)));
if (Constants.LOGVV) {
Log.v(Constants.TAG, "purging " + file.getAbsolutePath() + " for " +
file.length() + " bytes");
}
totalFreed += file.length();
file.delete();
- long id = cursor.getLong(cursor.getColumnIndex(Downloads._ID));
+ long id = cursor.getLong(cursor.getColumnIndex(Downloads.Impl._ID));
context.getContentResolver().delete(
- ContentUris.withAppendedId(Downloads.CONTENT_URI, id), null, null);
+ ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, id), null, null);
cursor.moveToNext();
}
} finally {