From cf79a11f9fee88daf48aa71b1d521fc5e07bf839 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Thu, 12 Nov 2009 18:46:14 -0800 Subject: eclair snapshot --- src/com/android/providers/downloads/Constants.java | 9 +- .../providers/downloads/DownloadFileInfo.java | 16 +- .../android/providers/downloads/DownloadInfo.java | 155 +++++------ .../providers/downloads/DownloadNotification.java | 107 ++++---- .../providers/downloads/DownloadProvider.java | 152 +++++------ .../providers/downloads/DownloadReceiver.java | 43 ++- .../providers/downloads/DownloadService.java | 297 +++++++++++---------- .../providers/downloads/DownloadThread.java | 240 ++++++++++------- src/com/android/providers/downloads/Helpers.java | 17 +- 9 files changed, 564 insertions(+), 472 deletions(-) (limited to 'src') diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java index ba7dfb3c..5cf13531 100644 --- a/src/com/android/providers/downloads/Constants.java +++ b/src/com/android/providers/downloads/Constants.java @@ -29,7 +29,7 @@ public class Constants { public static final String TAG = "DownloadManager"; /** The column that used to be used for the HTTP method of the request */ - public static final String RETRY_AFTER___REDIRECT_COUNT = "method"; + public static final String RETRY_AFTER_X_REDIRECT_COUNT = "method"; /** The column that used to be used for the magic OTA update filename */ public static final String OTA_UPDATE = "otaupdate"; @@ -140,12 +140,15 @@ public class Constants { */ public static final int RETRY_FIRST_DELAY = 30; + /** Enable separate connectivity logging */ + static final boolean LOGX = false; + /** Enable verbose logging - use with "setprop log.tag.DownloadManager VERBOSE" */ - private static final boolean LOCAL_LOGV = true; + private static final boolean LOCAL_LOGV = false; public static final boolean LOGV = Config.LOGV || (Config.LOGD && LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE)); /** Enable super-verbose logging */ - private static final boolean LOCAL_LOGVV = true; + private static final boolean LOCAL_LOGVV = false; public static final boolean LOGVV = LOCAL_LOGVV && LOGV; } diff --git a/src/com/android/providers/downloads/DownloadFileInfo.java b/src/com/android/providers/downloads/DownloadFileInfo.java index 29cbd940..ce423880 100644 --- a/src/com/android/providers/downloads/DownloadFileInfo.java +++ b/src/com/android/providers/downloads/DownloadFileInfo.java @@ -22,13 +22,13 @@ import java.io.FileOutputStream; * Stores information about the file in which a download gets saved. */ public class DownloadFileInfo { - public DownloadFileInfo(String filename, FileOutputStream stream, int status) { - this.filename = filename; - this.stream = stream; - this.status = status; - } + String mFileName; + FileOutputStream mStream; + int mStatus; - String filename; - FileOutputStream stream; - int status; + public DownloadFileInfo(String fileName, FileOutputStream stream, int status) { + mFileName = fileName; + mStream = stream; + mStatus = status; + } } diff --git a/src/com/android/providers/downloads/DownloadInfo.java b/src/com/android/providers/downloads/DownloadInfo.java index e051f41a..88cdede2 100644 --- a/src/com/android/providers/downloads/DownloadInfo.java +++ b/src/com/android/providers/downloads/DownloadInfo.java @@ -16,81 +16,84 @@ package com.android.providers.downloads; -import android.net.Uri; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.provider.Downloads; /** * Stores information about an individual download. */ public class DownloadInfo { - public int id; - public String uri; - public boolean noIntegrity; - public String hint; - public String filename; - public String mimetype; - public int destination; - public int visibility; - public int control; - public int status; - public int numFailed; - public int retryAfter; - public int redirectCount; - public long lastMod; - public String pckg; - public String clazz; - public String extras; - public String cookies; - public String userAgent; - public String referer; - public int totalBytes; - public int currentBytes; - public String etag; - public boolean mediaScanned; + public int mId; + public String mUri; + public boolean mNoIntegrity; + public String mHint; + public String mFileName; + public String mMimeType; + public int mDestination; + public int mVisibility; + public int mControl; + public int mStatus; + public int mNumFailed; + public int mRetryAfter; + public int mRedirectCount; + public long mLastMod; + public String mPackage; + public String mClass; + public String mExtras; + public String mCookies; + public String mUserAgent; + public String mReferer; + public int mTotalBytes; + public int mCurrentBytes; + public String mETag; + public boolean mMediaScanned; + + public int mFuzz; - public volatile boolean hasActiveThread; + public volatile boolean mHasActiveThread; public DownloadInfo(int id, String uri, boolean noIntegrity, - String hint, String filename, - String mimetype, int destination, int visibility, int control, + String hint, String fileName, + String mimeType, int destination, int visibility, int control, int status, int numFailed, int retryAfter, int redirectCount, long lastMod, String pckg, String clazz, String extras, String cookies, - String userAgent, String referer, int totalBytes, int currentBytes, String etag, + String userAgent, String referer, int totalBytes, int currentBytes, String eTag, boolean mediaScanned) { - this.id = id; - this.uri = uri; - this.noIntegrity = noIntegrity; - this.hint = hint; - this.filename = filename; - this.mimetype = mimetype; - this.destination = destination; - this.visibility = visibility; - this.control = control; - this.status = status; - this.numFailed = numFailed; - this.retryAfter = retryAfter; - this.redirectCount = redirectCount; - this.lastMod = lastMod; - this.pckg = pckg; - this.clazz = clazz; - this.extras = extras; - this.cookies = cookies; - this.userAgent = userAgent; - this.referer = referer; - this.totalBytes = totalBytes; - this.currentBytes = currentBytes; - this.etag = etag; - this.mediaScanned = mediaScanned; + mId = id; + mUri = uri; + mNoIntegrity = noIntegrity; + mHint = hint; + mFileName = fileName; + mMimeType = mimeType; + mDestination = destination; + mVisibility = visibility; + mControl = control; + mStatus = status; + mNumFailed = numFailed; + mRetryAfter = retryAfter; + mRedirectCount = redirectCount; + mLastMod = lastMod; + mPackage = pckg; + mClass = clazz; + mExtras = extras; + mCookies = cookies; + mUserAgent = userAgent; + mReferer = referer; + mTotalBytes = totalBytes; + mCurrentBytes = currentBytes; + mETag = eTag; + mMediaScanned = mediaScanned; + mFuzz = Helpers.sRandom.nextInt(1001); } public void sendIntentIfRequested(Uri contentUri, Context context) { - if (pckg != null && clazz != null) { - Intent intent = new Intent(Downloads.DOWNLOAD_COMPLETED_ACTION); - intent.setClassName(pckg, clazz); - if (extras != null) { - intent.putExtra(Downloads.NOTIFICATION_EXTRAS, extras); + if (mPackage != null && mClass != null) { + Intent intent = new Intent(Downloads.ACTION_DOWNLOAD_COMPLETED); + intent.setClassName(mPackage, mClass); + if (mExtras != null) { + intent.putExtra(Downloads.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 @@ -105,12 +108,12 @@ public class DownloadInfo { * be called when numFailed > 0. */ public long restartTime() { - if (retryAfter > 0) { - return lastMod + retryAfter; + if (mRetryAfter > 0) { + return mLastMod + mRetryAfter; } - return lastMod + + return mLastMod + Constants.RETRY_FIRST_DELAY * - (1000 + Helpers.rnd.nextInt(1001)) * (1 << (numFailed - 1)); + (1000 + mFuzz) * (1 << (mNumFailed - 1)); } /** @@ -118,25 +121,25 @@ public class DownloadInfo { * should be started. */ public boolean isReadyToStart(long now) { - if (control == Downloads.CONTROL_PAUSED) { + if (mControl == Downloads.CONTROL_PAUSED) { // the download is paused, so it's not going to start return false; } - if (status == 0) { + if (mStatus == 0) { // status hasn't been initialized yet, this is a new download return true; } - if (status == Downloads.STATUS_PENDING) { + if (mStatus == Downloads.STATUS_PENDING) { // download is explicit marked as ready to start return true; } - if (status == Downloads.STATUS_RUNNING) { + if (mStatus == Downloads.STATUS_RUNNING) { // download was interrupted (process killed, loss of power) while it was running, // without a chance to update the database return true; } - if (status == Downloads.STATUS_RUNNING_PAUSED) { - if (numFailed == 0) { + if (mStatus == Downloads.STATUS_RUNNING_PAUSED) { + if (mNumFailed == 0) { // download is waiting for network connectivity to return before it can resume return true; } @@ -157,20 +160,20 @@ public class DownloadInfo { * by checking the status. */ public boolean isReadyToRestart(long now) { - if (control == Downloads.CONTROL_PAUSED) { + if (mControl == Downloads.CONTROL_PAUSED) { // the download is paused, so it's not going to restart return false; } - if (status == 0) { + if (mStatus == 0) { // download hadn't been initialized yet return true; } - if (status == Downloads.STATUS_PENDING) { + if (mStatus == Downloads.STATUS_PENDING) { // download is explicit marked as ready to start return true; } - if (status == Downloads.STATUS_RUNNING_PAUSED) { - if (numFailed == 0) { + if (mStatus == Downloads.STATUS_RUNNING_PAUSED) { + if (mNumFailed == 0) { // download is waiting for network connectivity to return before it can resume return true; } @@ -187,10 +190,10 @@ public class DownloadInfo { * completion. */ public boolean hasCompletionNotification() { - if (!Downloads.isStatusCompleted(status)) { + if (!Downloads.isStatusCompleted(mStatus)) { return false; } - if (visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) { + if (mVisibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) { return true; } return false; @@ -203,7 +206,7 @@ public class DownloadInfo { if (!available) { return false; } - if (destination == Downloads.DESTINATION_CACHE_PARTITION_NOROAMING) { + if (mDestination == Downloads.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 ed17ab7a..9f54190e 100644 --- a/src/com/android/providers/downloads/DownloadNotification.java +++ b/src/com/android/providers/downloads/DownloadNotification.java @@ -43,14 +43,15 @@ class DownloadNotification { static final String LOGTAG = "DownloadNotification"; static final String WHERE_RUNNING = - "(" + Downloads.STATUS + " >= '100') AND (" + - Downloads.STATUS + " <= '199') AND (" + - Downloads.VISIBILITY + " IS NULL OR " + - Downloads.VISIBILITY + " == '" + Downloads.VISIBILITY_VISIBLE + "' OR " + - Downloads.VISIBILITY + " == '" + Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + "')"; + "(" + 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 + "')"; static final String WHERE_COMPLETED = - Downloads.STATUS + " >= '200' AND " + - Downloads.VISIBILITY + " == '" + Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + "'"; + Downloads.COLUMN_STATUS + " >= '200' AND " + + Downloads.COLUMN_VISIBILITY + " == '" + Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + "'"; /** @@ -60,28 +61,28 @@ class DownloadNotification { * */ static class NotificationItem { - int id; // This first db _id for the download for the app - int totalCurrent = 0; - int totalTotal = 0; - int titleCount = 0; - String packageName; // App package name - String description; - String[] titles = new String[2]; // download titles. + int mId; // This first db _id for the download for the app + int mTotalCurrent = 0; + int mTotalTotal = 0; + int mTitleCount = 0; + String mPackageName; // App package name + String mDescription; + String[] mTitles = new String[2]; // download titles. /* * Add a second download to this notification item. */ void addItem(String title, int currentBytes, int totalBytes) { - totalCurrent += currentBytes; - if (totalBytes <= 0 || totalTotal == -1) { - totalTotal = -1; + mTotalCurrent += currentBytes; + if (totalBytes <= 0 || mTotalTotal == -1) { + mTotalTotal = -1; } else { - totalTotal += totalBytes; + mTotalTotal += totalBytes; } - if (titleCount < 2) { - titles[titleCount] = title; + if (mTitleCount < 2) { + mTitles[mTitleCount] = title; } - titleCount++; + mTitleCount++; } } @@ -110,11 +111,14 @@ class DownloadNotification { // Active downloads Cursor c = mContext.getContentResolver().query( Downloads.CONTENT_URI, new String [] { - Downloads._ID, Downloads.TITLE, Downloads.DESCRIPTION, - Downloads.NOTIFICATION_PACKAGE, - Downloads.NOTIFICATION_CLASS, - Downloads.CURRENT_BYTES, Downloads.TOTAL_BYTES, - Downloads.STATUS, Downloads._DATA + 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 }, WHERE_RUNNING, null, Downloads._ID); @@ -148,9 +152,9 @@ class DownloadNotification { mNotifications.get(packageName).addItem(title, progress, max); } else { NotificationItem item = new NotificationItem(); - item.id = c.getInt(idColumn); - item.packageName = packageName; - item.description = c.getString(descColumn); + item.mId = c.getInt(idColumn); + item.mPackageName = packageName; + item.mDescription = c.getString(descColumn); String className = c.getString(classOwnerColumn); item.addItem(title, progress, max); mNotifications.put(packageName, item); @@ -171,26 +175,26 @@ class DownloadNotification { RemoteViews expandedView = new RemoteViews( "com.android.providers.downloads", R.layout.status_bar_ongoing_event_progress_bar); - StringBuilder title = new StringBuilder(item.titles[0]); - if (item.titleCount > 1) { + StringBuilder title = new StringBuilder(item.mTitles[0]); + if (item.mTitleCount > 1) { title.append(mContext.getString(R.string.notification_filename_separator)); - title.append(item.titles[1]); - n.number = item.titleCount; - if (item.titleCount > 2) { + title.append(item.mTitles[1]); + n.number = item.mTitleCount; + if (item.mTitleCount > 2) { title.append(mContext.getString(R.string.notification_filename_extras, - new Object[] { Integer.valueOf(item.titleCount - 2) })); + new Object[] { Integer.valueOf(item.mTitleCount - 2) })); } } else { expandedView.setTextViewText(R.id.description, - item.description); + item.mDescription); } expandedView.setTextViewText(R.id.title, title); expandedView.setProgressBar(R.id.progress_bar, - item.totalTotal, - item.totalCurrent, - item.totalTotal == -1); + item.mTotalTotal, + item.mTotalCurrent, + item.mTotalTotal == -1); expandedView.setTextViewText(R.id.progress_text, - getDownloadingText(item.totalTotal, item.totalCurrent)); + getDownloadingText(item.mTotalTotal, item.mTotalCurrent)); expandedView.setImageViewResource(R.id.appIcon, android.R.drawable.stat_sys_download); n.contentView = expandedView; @@ -198,12 +202,12 @@ 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.id)); - intent.putExtra("multiple", item.titleCount > 1); + intent.setData(Uri.parse(Downloads.CONTENT_URI + "/" + item.mId)); + intent.putExtra("multiple", item.mTitleCount > 1); n.contentIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); - mNotificationMgr.notify(item.id, n); + mNotificationMgr.notify(item.mId, n); } } @@ -212,12 +216,17 @@ class DownloadNotification { // Completed downloads Cursor c = mContext.getContentResolver().query( Downloads.CONTENT_URI, new String [] { - Downloads._ID, Downloads.TITLE, Downloads.DESCRIPTION, - Downloads.NOTIFICATION_PACKAGE, - Downloads.NOTIFICATION_CLASS, - Downloads.CURRENT_BYTES, Downloads.TOTAL_BYTES, - Downloads.STATUS, Downloads._DATA, - Downloads.LAST_MODIFICATION, Downloads.DESTINATION + 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 }, WHERE_COMPLETED, null, Downloads._ID); diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java index e5f25762..f0190fd1 100644 --- a/src/com/android/providers/downloads/DownloadProvider.java +++ b/src/com/android/providers/downloads/DownloadProvider.java @@ -26,10 +26,10 @@ import android.database.CrossProcessCursor; import android.database.Cursor; import android.database.CursorWindow; import android.database.CursorWrapper; +import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; -import android.database.SQLException; import android.net.Uri; import android.os.Binder; import android.os.ParcelFileDescriptor; @@ -40,7 +40,6 @@ import android.util.Log; import java.io.File; import java.io.FileNotFoundException; -import java.io.IOException; import java.util.HashSet; @@ -78,20 +77,20 @@ public final class DownloadProvider extends ContentProvider { private static final String[] sAppReadableColumnsArray = new String[] { Downloads._ID, - Downloads.APP_DATA, + Downloads.COLUMN_APP_DATA, Downloads._DATA, - Downloads.MIMETYPE, - Downloads.VISIBILITY, - Downloads.DESTINATION, - Downloads.CONTROL, - Downloads.STATUS, - Downloads.LAST_MODIFICATION, - Downloads.NOTIFICATION_PACKAGE, - Downloads.NOTIFICATION_CLASS, - Downloads.TOTAL_BYTES, - Downloads.CURRENT_BYTES, - Downloads.TITLE, - Downloads.DESCRIPTION + 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 }; private static HashSet sAppReadableColumnsSet; @@ -201,34 +200,34 @@ public final class DownloadProvider extends ContentProvider { try { db.execSQL("CREATE TABLE " + DB_TABLE + "(" + Downloads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - Downloads.URI + " TEXT, " + - Constants.RETRY_AFTER___REDIRECT_COUNT + " INTEGER, " + - Downloads.APP_DATA + " TEXT, " + - Downloads.NO_INTEGRITY + " BOOLEAN, " + - Downloads.FILENAME_HINT + " TEXT, " + + Downloads.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, " + Constants.OTA_UPDATE + " BOOLEAN, " + Downloads._DATA + " TEXT, " + - Downloads.MIMETYPE + " TEXT, " + - Downloads.DESTINATION + " INTEGER, " + + Downloads.COLUMN_MIME_TYPE + " TEXT, " + + Downloads.COLUMN_DESTINATION + " INTEGER, " + Constants.NO_SYSTEM_FILES + " BOOLEAN, " + - Downloads.VISIBILITY + " INTEGER, " + - Downloads.CONTROL + " INTEGER, " + - Downloads.STATUS + " INTEGER, " + + Downloads.COLUMN_VISIBILITY + " INTEGER, " + + Downloads.COLUMN_CONTROL + " INTEGER, " + + Downloads.COLUMN_STATUS + " INTEGER, " + Constants.FAILED_CONNECTIONS + " INTEGER, " + - Downloads.LAST_MODIFICATION + " BIGINT, " + - Downloads.NOTIFICATION_PACKAGE + " TEXT, " + - Downloads.NOTIFICATION_CLASS + " TEXT, " + - Downloads.NOTIFICATION_EXTRAS + " TEXT, " + - Downloads.COOKIE_DATA + " TEXT, " + - Downloads.USER_AGENT + " TEXT, " + - Downloads.REFERER + " TEXT, " + - Downloads.TOTAL_BYTES + " INTEGER, " + - Downloads.CURRENT_BYTES + " 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, " + Constants.ETAG + " TEXT, " + Constants.UID + " INTEGER, " + - Downloads.OTHER_UID + " INTEGER, " + - Downloads.TITLE + " TEXT, " + - Downloads.DESCRIPTION + " TEXT, " + + Downloads.COLUMN_OTHER_UID + " INTEGER, " + + Downloads.COLUMN_TITLE + " TEXT, " + + Downloads.COLUMN_DESCRIPTION + " TEXT, " + Constants.MEDIA_SCANNED + " BOOLEAN);"); } catch (SQLException ex) { Log.e(Constants.TAG, "couldn't create table in downloads database"); @@ -264,12 +263,12 @@ public final class DownloadProvider extends ContentProvider { ContentValues filteredValues = new ContentValues(); - copyString(Downloads.URI, values, filteredValues); - copyString(Downloads.APP_DATA, values, filteredValues); - copyBoolean(Downloads.NO_INTEGRITY, values, filteredValues); - copyString(Downloads.FILENAME_HINT, values, filteredValues); - copyString(Downloads.MIMETYPE, values, filteredValues); - Integer dest = values.getAsInteger(Downloads.DESTINATION); + 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); if (dest != null) { if (getContext().checkCallingPermission(Downloads.PERMISSION_ACCESS_ADVANCED) != PackageManager.PERMISSION_GRANTED @@ -277,57 +276,57 @@ public final class DownloadProvider extends ContentProvider { && dest != Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE) { throw new SecurityException("unauthorized destination code"); } - filteredValues.put(Downloads.DESTINATION, dest); + filteredValues.put(Downloads.COLUMN_DESTINATION, dest); } - Integer vis = values.getAsInteger(Downloads.VISIBILITY); + Integer vis = values.getAsInteger(Downloads.COLUMN_VISIBILITY); if (vis == null) { if (dest == Downloads.DESTINATION_EXTERNAL) { - filteredValues.put(Downloads.VISIBILITY, + filteredValues.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); } else { - filteredValues.put(Downloads.VISIBILITY, Downloads.VISIBILITY_HIDDEN); + filteredValues.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_HIDDEN); } } else { - filteredValues.put(Downloads.VISIBILITY, vis); + filteredValues.put(Downloads.COLUMN_VISIBILITY, vis); } - copyInteger(Downloads.CONTROL, values, filteredValues); - filteredValues.put(Downloads.STATUS, Downloads.STATUS_PENDING); - filteredValues.put(Downloads.LAST_MODIFICATION, System.currentTimeMillis()); - String pckg = values.getAsString(Downloads.NOTIFICATION_PACKAGE); - String clazz = values.getAsString(Downloads.NOTIFICATION_CLASS); + 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); if (pckg != null && clazz != null) { int uid = Binder.getCallingUid(); try { if (uid == 0 || getContext().getPackageManager().getApplicationInfo(pckg, 0).uid == uid) { - filteredValues.put(Downloads.NOTIFICATION_PACKAGE, pckg); - filteredValues.put(Downloads.NOTIFICATION_CLASS, clazz); + filteredValues.put(Downloads.COLUMN_NOTIFICATION_PACKAGE, pckg); + filteredValues.put(Downloads.COLUMN_NOTIFICATION_CLASS, clazz); } } catch (PackageManager.NameNotFoundException ex) { /* ignored for now */ } } - copyString(Downloads.NOTIFICATION_EXTRAS, values, filteredValues); - copyString(Downloads.COOKIE_DATA, values, filteredValues); - copyString(Downloads.USER_AGENT, values, filteredValues); - copyString(Downloads.REFERER, values, filteredValues); + 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) == PackageManager.PERMISSION_GRANTED) { - copyInteger(Downloads.OTHER_UID, values, filteredValues); + copyInteger(Downloads.COLUMN_OTHER_UID, values, filteredValues); } filteredValues.put(Constants.UID, Binder.getCallingUid()); if (Binder.getCallingUid() == 0) { copyInteger(Constants.UID, values, filteredValues); } - copyString(Downloads.TITLE, values, filteredValues); - copyString(Downloads.DESCRIPTION, values, filteredValues); + copyString(Downloads.COLUMN_TITLE, values, filteredValues); + copyString(Downloads.COLUMN_DESCRIPTION, values, filteredValues); if (Constants.LOGVV) { Log.v(Constants.TAG, "initiating download with UID " + filteredValues.getAsInteger(Constants.UID)); - if (filteredValues.containsKey(Downloads.OTHER_UID)) { + if (filteredValues.containsKey(Downloads.COLUMN_OTHER_UID)) { Log.v(Constants.TAG, "other UID " + - filteredValues.getAsInteger(Downloads.OTHER_UID)); + filteredValues.getAsInteger(Downloads.COLUMN_OTHER_UID)); } } @@ -387,12 +386,13 @@ public final class DownloadProvider extends ContentProvider { } } - if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0) { + if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0 && + Process.supportsProcesses()) { if (!emptyWhere) { qb.appendWhere(" AND "); } qb.appendWhere("( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " - + Downloads.OTHER_UID + "=" + Binder.getCallingUid() + " )"); + + Downloads.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"); emptyWhere = false; if (projection == null) { @@ -489,16 +489,16 @@ public final class DownloadProvider extends ContentProvider { ContentValues filteredValues; if (Binder.getCallingPid() != Process.myPid()) { filteredValues = new ContentValues(); - copyString(Downloads.APP_DATA, values, filteredValues); - copyInteger(Downloads.VISIBILITY, values, filteredValues); - Integer i = values.getAsInteger(Downloads.CONTROL); + copyString(Downloads.COLUMN_APP_DATA, values, filteredValues); + copyInteger(Downloads.COLUMN_VISIBILITY, values, filteredValues); + Integer i = values.getAsInteger(Downloads.COLUMN_CONTROL); if (i != null) { - filteredValues.put(Downloads.CONTROL, i); + filteredValues.put(Downloads.COLUMN_CONTROL, i); startService = true; } - copyInteger(Downloads.CONTROL, values, filteredValues); - copyString(Downloads.TITLE, values, filteredValues); - copyString(Downloads.DESCRIPTION, values, filteredValues); + copyInteger(Downloads.COLUMN_CONTROL, values, filteredValues); + copyString(Downloads.COLUMN_TITLE, values, filteredValues); + copyString(Downloads.COLUMN_DESCRIPTION, values, filteredValues); } else { filteredValues = values; } @@ -523,7 +523,7 @@ public final class DownloadProvider extends ContentProvider { } if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0) { myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " - + Downloads.OTHER_UID + "=" + Binder.getCallingUid() + " )"; + + Downloads.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"; } if (filteredValues.size() > 0) { count = db.update(DB_TABLE, filteredValues, myWhere, whereArgs); @@ -579,7 +579,7 @@ public final class DownloadProvider extends ContentProvider { } if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0) { myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " - + Downloads.OTHER_UID + "=" + Binder.getCallingUid() + " )"; + + Downloads.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"; } count = db.delete(DB_TABLE, myWhere, whereArgs); break; @@ -673,7 +673,7 @@ public final class DownloadProvider extends ContentProvider { throw new FileNotFoundException("couldn't open file"); } else { ContentValues values = new ContentValues(); - values.put(Downloads.LAST_MODIFICATION, System.currentTimeMillis()); + values.put(Downloads.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 03a37186..2065c649 100644 --- a/src/com/android/providers/downloads/DownloadReceiver.java +++ b/src/com/android/providers/downloads/DownloadReceiver.java @@ -23,18 +23,15 @@ import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.database.Cursor; -import android.provider.Downloads; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; +import android.provider.Downloads; import android.util.Config; import android.util.Log; import java.io.File; -import java.util.List; /** * Receives system broadcasts (boot, network connectivity) @@ -54,7 +51,22 @@ public class DownloadReceiver extends BroadcastReceiver { NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); if (info != null && info.isConnected()) { + if (Constants.LOGX) { + if (Helpers.isNetworkAvailable(context)) { + Log.i(Constants.TAG, "Broadcast: Network Up"); + } else { + Log.i(Constants.TAG, "Broadcast: Network Up, Actually Down"); + } + } context.startService(new Intent(context, DownloadService.class)); + } else { + if (Constants.LOGX) { + if (Helpers.isNetworkAvailable(context)) { + Log.i(Constants.TAG, "Broadcast: Network Down, Actually Up"); + } else { + Log.i(Constants.TAG, "Broadcast: Network Down"); + } + } } } else if (intent.getAction().equals(Constants.ACTION_RETRY)) { if (Constants.LOGVV) { @@ -74,20 +86,22 @@ public class DownloadReceiver extends BroadcastReceiver { intent.getData(), null, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { - int statusColumn = cursor.getColumnIndexOrThrow(Downloads.STATUS); + int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS); int status = cursor.getInt(statusColumn); - int visibilityColumn = cursor.getColumnIndexOrThrow(Downloads.VISIBILITY); + int visibilityColumn = + cursor.getColumnIndexOrThrow(Downloads.COLUMN_VISIBILITY); int visibility = cursor.getInt(visibilityColumn); if (Downloads.isStatusCompleted(status) && visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) { ContentValues values = new ContentValues(); - values.put(Downloads.VISIBILITY, Downloads.VISIBILITY_VISIBLE); + values.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_VISIBLE); context.getContentResolver().update(intent.getData(), values, null, null); } if (intent.getAction().equals(Constants.ACTION_OPEN)) { int filenameColumn = cursor.getColumnIndexOrThrow(Downloads._DATA); - int mimetypeColumn = cursor.getColumnIndexOrThrow(Downloads.MIMETYPE); + int mimetypeColumn = + cursor.getColumnIndexOrThrow(Downloads.COLUMN_MIME_TYPE); String filename = cursor.getString(filenameColumn); String mimetype = cursor.getString(mimetypeColumn); Uri path = Uri.parse(filename); @@ -109,13 +123,13 @@ public class DownloadReceiver extends BroadcastReceiver { } } else { int packageColumn = - cursor.getColumnIndexOrThrow(Downloads.NOTIFICATION_PACKAGE); + cursor.getColumnIndexOrThrow(Downloads.COLUMN_NOTIFICATION_PACKAGE); int classColumn = - cursor.getColumnIndexOrThrow(Downloads.NOTIFICATION_CLASS); + cursor.getColumnIndexOrThrow(Downloads.COLUMN_NOTIFICATION_CLASS); String pckg = cursor.getString(packageColumn); String clazz = cursor.getString(classColumn); if (pckg != null && clazz != null) { - Intent appIntent = new Intent(Downloads.NOTIFICATION_CLICKED_ACTION); + Intent appIntent = new Intent(Downloads.ACTION_NOTIFICATION_CLICKED); appIntent.setClassName(pckg, clazz); if (intent.getBooleanExtra("multiple", true)) { appIntent.setData(Downloads.CONTENT_URI); @@ -141,14 +155,15 @@ public class DownloadReceiver extends BroadcastReceiver { intent.getData(), null, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { - int statusColumn = cursor.getColumnIndexOrThrow(Downloads.STATUS); + int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS); int status = cursor.getInt(statusColumn); - int visibilityColumn = cursor.getColumnIndexOrThrow(Downloads.VISIBILITY); + int visibilityColumn = + cursor.getColumnIndexOrThrow(Downloads.COLUMN_VISIBILITY); int visibility = cursor.getInt(visibilityColumn); if (Downloads.isStatusCompleted(status) && visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) { ContentValues values = new ContentValues(); - values.put(Downloads.VISIBILITY, Downloads.VISIBILITY_VISIBLE); + values.put(Downloads.COLUMN_VISIBILITY, Downloads.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 0600cfb6..a246d29f 100644 --- a/src/com/android/providers/downloads/DownloadService.java +++ b/src/com/android/providers/downloads/DownloadService.java @@ -26,20 +26,20 @@ import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.ServiceConnection; +import android.database.CharArrayBuffer; import android.database.ContentObserver; import android.database.Cursor; -import android.database.CharArrayBuffer; import android.drm.mobile1.DrmRawContent; import android.media.IMediaScannerService; import android.net.Uri; -import android.os.RemoteException; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Process; +import android.os.RemoteException; import android.provider.Downloads; import android.util.Config; import android.util.Log; @@ -78,13 +78,13 @@ public class DownloadService extends Service { * The thread that updates the internal download list from the content * provider. */ - private UpdateThread updateThread; + private UpdateThread mUpdateThread; /** * Whether the internal download list should be updated from the content * provider. */ - private boolean pendingUpdate; + private boolean mPendingUpdate; /** * The ServiceConnection object that tells us when we're connected to and disconnected from @@ -107,7 +107,7 @@ public class DownloadService extends Service { /** * Array used when extracting strings from content provider */ - private CharArrayBuffer newChars; + private CharArrayBuffer mNewChars; /* ------------ Inner Classes ------------ */ @@ -247,10 +247,10 @@ public class DownloadService extends Service { */ private void updateFromProvider() { synchronized (this) { - pendingUpdate = true; - if (updateThread == null) { - updateThread = new UpdateThread(); - updateThread.start(); + mPendingUpdate = true; + if (mUpdateThread == null) { + mUpdateThread = new UpdateThread(); + mUpdateThread.start(); } } } @@ -269,12 +269,12 @@ public class DownloadService extends Service { long wakeUp = Long.MAX_VALUE; for (;;) { synchronized (DownloadService.this) { - if (updateThread != this) { + if (mUpdateThread != this) { throw new IllegalStateException( "multiple UpdateThreads in DownloadService"); } - if (!pendingUpdate) { - updateThread = null; + if (!mPendingUpdate) { + mUpdateThread = null; if (!keepService) { stopSelf(); } @@ -298,10 +298,10 @@ public class DownloadService extends Service { } } oldChars = null; - newChars = null; + mNewChars = null; return; } - pendingUpdate = false; + mPendingUpdate = false; } boolean networkAvailable = Helpers.isNetworkAvailable(DownloadService.this); boolean networkRoaming = Helpers.isNetworkRoaming(DownloadService.this); @@ -311,6 +311,7 @@ public class DownloadService extends Service { null, null, null, Downloads._ID); if (cursor == null) { + // TODO: this doesn't look right, it'd leave the loop in an inconsistent state return; } @@ -348,7 +349,7 @@ public class DownloadService extends Service { // We're beyond the end of the cursor but there's still some // stuff in the local array, which can only be junk if (Constants.LOGVV) { - int arrayId = ((DownloadInfo) mDownloads.get(arrayPos)).id; + int arrayId = ((DownloadInfo) mDownloads.get(arrayPos)).mId; Log.v(Constants.TAG, "Array update: trimming " + arrayId + " @ " + arrayPos); } @@ -362,7 +363,7 @@ public class DownloadService extends Service { if (arrayPos == mDownloads.size()) { insertDownload(cursor, arrayPos, networkAvailable, networkRoaming, now); if (Constants.LOGVV) { - Log.v(Constants.TAG, "Array update: inserting " + + Log.v(Constants.TAG, "Array update: appending " + id + " @ " + arrayPos); } if (shouldScanFile(arrayPos) @@ -383,7 +384,7 @@ public class DownloadService extends Service { cursor.moveToNext(); isAfterLast = cursor.isAfterLast(); } else { - int arrayId = mDownloads.get(arrayPos).id; + int arrayId = mDownloads.get(arrayPos).mId; if (arrayId < id) { // The array entry isn't in the cursor @@ -421,7 +422,7 @@ public class DownloadService extends Service { } else { // This cursor entry didn't exist in the stored array if (Constants.LOGVV) { - Log.v(Constants.TAG, "Array update: appending " + + Log.v(Constants.TAG, "Array update: inserting " + id + " @ " + arrayPos); } insertDownload( @@ -516,8 +517,8 @@ public class DownloadService extends Service { private void trimDatabase() { Cursor cursor = getContentResolver().query(Downloads.CONTENT_URI, new String[] { Downloads._ID }, - Downloads.STATUS + " >= '200'", null, - Downloads.LAST_MODIFICATION); + Downloads.COLUMN_STATUS + " >= '200'", null, + Downloads.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"); @@ -546,70 +547,72 @@ public class DownloadService extends Service { private void insertDownload( Cursor cursor, int arrayPos, boolean networkAvailable, boolean networkRoaming, long now) { - int statusColumn = cursor.getColumnIndexOrThrow(Downloads.STATUS); + int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS); int failedColumn = cursor.getColumnIndexOrThrow(Constants.FAILED_CONNECTIONS); int retryRedirect = - cursor.getInt(cursor.getColumnIndexOrThrow(Constants.RETRY_AFTER___REDIRECT_COUNT)); + 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.URI)), - cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.NO_INTEGRITY)) == 1, - cursor.getString(cursor.getColumnIndexOrThrow(Downloads.FILENAME_HINT)), + 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.MIMETYPE)), - cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.DESTINATION)), - cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.VISIBILITY)), - cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.CONTROL)), + 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(statusColumn), cursor.getInt(failedColumn), retryRedirect & 0xfffffff, retryRedirect >> 28, - cursor.getLong(cursor.getColumnIndexOrThrow(Downloads.LAST_MODIFICATION)), - cursor.getString(cursor.getColumnIndexOrThrow(Downloads.NOTIFICATION_PACKAGE)), - cursor.getString(cursor.getColumnIndexOrThrow(Downloads.NOTIFICATION_CLASS)), - cursor.getString(cursor.getColumnIndexOrThrow(Downloads.NOTIFICATION_EXTRAS)), - cursor.getString(cursor.getColumnIndexOrThrow(Downloads.COOKIE_DATA)), - cursor.getString(cursor.getColumnIndexOrThrow(Downloads.USER_AGENT)), - cursor.getString(cursor.getColumnIndexOrThrow(Downloads.REFERER)), - cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.TOTAL_BYTES)), - cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.CURRENT_BYTES)), + cursor.getLong(cursor.getColumnIndexOrThrow(Downloads.COLUMN_LAST_MODIFICATION)), + cursor.getString(cursor.getColumnIndexOrThrow( + Downloads.COLUMN_NOTIFICATION_PACKAGE)), + cursor.getString(cursor.getColumnIndexOrThrow(Downloads.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)), cursor.getString(cursor.getColumnIndexOrThrow(Constants.ETAG)), cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) == 1); if (Constants.LOGVV) { Log.v(Constants.TAG, "Service adding new entry"); - Log.v(Constants.TAG, "ID : " + info.id); - Log.v(Constants.TAG, "URI : " + ((info.uri != null) ? "yes" : "no")); - Log.v(Constants.TAG, "NO_INTEG: " + info.noIntegrity); - Log.v(Constants.TAG, "HINT : " + info.hint); - Log.v(Constants.TAG, "FILENAME: " + info.filename); - Log.v(Constants.TAG, "MIMETYPE: " + info.mimetype); - Log.v(Constants.TAG, "DESTINAT: " + info.destination); - Log.v(Constants.TAG, "VISIBILI: " + info.visibility); - Log.v(Constants.TAG, "CONTROL : " + info.control); - Log.v(Constants.TAG, "STATUS : " + info.status); - Log.v(Constants.TAG, "FAILED_C: " + info.numFailed); - Log.v(Constants.TAG, "RETRY_AF: " + info.retryAfter); - Log.v(Constants.TAG, "REDIRECT: " + info.redirectCount); - Log.v(Constants.TAG, "LAST_MOD: " + info.lastMod); - Log.v(Constants.TAG, "PACKAGE : " + info.pckg); - Log.v(Constants.TAG, "CLASS : " + info.clazz); - Log.v(Constants.TAG, "COOKIES : " + ((info.cookies != null) ? "yes" : "no")); - Log.v(Constants.TAG, "AGENT : " + info.userAgent); - Log.v(Constants.TAG, "REFERER : " + ((info.referer != null) ? "yes" : "no")); - Log.v(Constants.TAG, "TOTAL : " + info.totalBytes); - Log.v(Constants.TAG, "CURRENT : " + info.currentBytes); - Log.v(Constants.TAG, "ETAG : " + info.etag); - Log.v(Constants.TAG, "SCANNED : " + info.mediaScanned); + Log.v(Constants.TAG, "ID : " + info.mId); + Log.v(Constants.TAG, "URI : " + ((info.mUri != null) ? "yes" : "no")); + Log.v(Constants.TAG, "NO_INTEG: " + info.mNoIntegrity); + Log.v(Constants.TAG, "HINT : " + info.mHint); + Log.v(Constants.TAG, "FILENAME: " + info.mFileName); + Log.v(Constants.TAG, "MIMETYPE: " + info.mMimeType); + Log.v(Constants.TAG, "DESTINAT: " + info.mDestination); + Log.v(Constants.TAG, "VISIBILI: " + info.mVisibility); + Log.v(Constants.TAG, "CONTROL : " + info.mControl); + Log.v(Constants.TAG, "STATUS : " + info.mStatus); + Log.v(Constants.TAG, "FAILED_C: " + info.mNumFailed); + Log.v(Constants.TAG, "RETRY_AF: " + info.mRetryAfter); + Log.v(Constants.TAG, "REDIRECT: " + info.mRedirectCount); + Log.v(Constants.TAG, "LAST_MOD: " + info.mLastMod); + Log.v(Constants.TAG, "PACKAGE : " + info.mPackage); + Log.v(Constants.TAG, "CLASS : " + info.mClass); + Log.v(Constants.TAG, "COOKIES : " + ((info.mCookies != null) ? "yes" : "no")); + Log.v(Constants.TAG, "AGENT : " + info.mUserAgent); + Log.v(Constants.TAG, "REFERER : " + ((info.mReferer != null) ? "yes" : "no")); + Log.v(Constants.TAG, "TOTAL : " + info.mTotalBytes); + Log.v(Constants.TAG, "CURRENT : " + info.mCurrentBytes); + Log.v(Constants.TAG, "ETAG : " + info.mETag); + Log.v(Constants.TAG, "SCANNED : " + info.mMediaScanned); } mDownloads.add(arrayPos, info); - if (info.status == 0 - && (info.destination == Downloads.DESTINATION_EXTERNAL - || info.destination == Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE) - && info.mimetype != null - && !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(info.mimetype)) { + if (info.mStatus == 0 + && (info.mDestination == Downloads.DESTINATION_EXTERNAL + || info.mDestination == Downloads.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. @@ -622,20 +625,20 @@ public class DownloadService extends Service { // prevent use from using content: so it's got to be file: or // nothing - mimetypeIntent.setDataAndType(Uri.fromParts("file", "", null), info.mimetype); + 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.mimetype); + Log.d(Constants.TAG, "no application to handle MIME type " + info.mMimeType); } - info.status = Downloads.STATUS_NOT_ACCEPTABLE; + info.mStatus = Downloads.STATUS_NOT_ACCEPTABLE; - Uri uri = ContentUris.withAppendedId(Downloads.CONTENT_URI, info.id); + Uri uri = ContentUris.withAppendedId(Downloads.CONTENT_URI, info.mId); ContentValues values = new ContentValues(); - values.put(Downloads.STATUS, Downloads.STATUS_NOT_ACCEPTABLE); + values.put(Downloads.COLUMN_STATUS, Downloads.STATUS_NOT_ACCEPTABLE); getContentResolver().update(uri, values, null, null); info.sendIntentIfRequested(uri, this); return; @@ -646,31 +649,31 @@ public class DownloadService extends Service { if (info.isReadyToStart(now)) { if (Constants.LOGV) { Log.v(Constants.TAG, "Service spawning thread to handle new download " + - info.id); + info.mId); } - if (info.hasActiveThread) { + if (info.mHasActiveThread) { throw new IllegalStateException("Multiple threads on same download on insert"); } - if (info.status != Downloads.STATUS_RUNNING) { - info.status = Downloads.STATUS_RUNNING; + if (info.mStatus != Downloads.STATUS_RUNNING) { + info.mStatus = Downloads.STATUS_RUNNING; ContentValues values = new ContentValues(); - values.put(Downloads.STATUS, info.status); + values.put(Downloads.COLUMN_STATUS, info.mStatus); getContentResolver().update( - ContentUris.withAppendedId(Downloads.CONTENT_URI, info.id), + ContentUris.withAppendedId(Downloads.CONTENT_URI, info.mId), values, null, null); } DownloadThread downloader = new DownloadThread(this, info); - info.hasActiveThread = true; + info.mHasActiveThread = true; downloader.start(); } } else { - if (info.status == 0 - || info.status == Downloads.STATUS_PENDING - || info.status == Downloads.STATUS_RUNNING) { - info.status = Downloads.STATUS_RUNNING_PAUSED; - Uri uri = ContentUris.withAppendedId(Downloads.CONTENT_URI, info.id); + 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); ContentValues values = new ContentValues(); - values.put(Downloads.STATUS, Downloads.STATUS_RUNNING_PAUSED); + values.put(Downloads.COLUMN_STATUS, Downloads.STATUS_RUNNING_PAUSED); getContentResolver().update(uri, values, null, null); } } @@ -683,65 +686,71 @@ 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.STATUS); + int statusColumn = cursor.getColumnIndexOrThrow(Downloads.COLUMN_STATUS); int failedColumn = cursor.getColumnIndexOrThrow(Constants.FAILED_CONNECTIONS); - info.id = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads._ID)); - info.uri = stringFromCursor(info.uri, cursor, Downloads.URI); - info.noIntegrity = - cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.NO_INTEGRITY)) == 1; - info.hint = stringFromCursor(info.hint, cursor, Downloads.FILENAME_HINT); - info.filename = stringFromCursor(info.filename, cursor, Downloads._DATA); - info.mimetype = stringFromCursor(info.mimetype, cursor, Downloads.MIMETYPE); - info.destination = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.DESTINATION)); - int newVisibility = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.VISIBILITY)); - if (info.visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED + 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.mDestination = cursor.getInt(cursor.getColumnIndexOrThrow( + Downloads.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.status)) { - mNotifier.mNotificationMgr.cancel(info.id); + && Downloads.isStatusCompleted(info.mStatus)) { + mNotifier.mNotificationMgr.cancel(info.mId); } - info.visibility = newVisibility; - synchronized(info) { - info.control = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.CONTROL)); + info.mVisibility = newVisibility; + synchronized (info) { + info.mControl = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.COLUMN_CONTROL)); } int newStatus = cursor.getInt(statusColumn); - if (!Downloads.isStatusCompleted(info.status) && Downloads.isStatusCompleted(newStatus)) { - mNotifier.mNotificationMgr.cancel(info.id); + if (!Downloads.isStatusCompleted(info.mStatus) && Downloads.isStatusCompleted(newStatus)) { + mNotifier.mNotificationMgr.cancel(info.mId); } - info.status = newStatus; - info.numFailed = cursor.getInt(failedColumn); + info.mStatus = newStatus; + info.mNumFailed = cursor.getInt(failedColumn); int retryRedirect = - cursor.getInt(cursor.getColumnIndexOrThrow(Constants.RETRY_AFTER___REDIRECT_COUNT)); - info.retryAfter = retryRedirect & 0xfffffff; - info.redirectCount = retryRedirect >> 28; - info.lastMod = cursor.getLong(cursor.getColumnIndexOrThrow(Downloads.LAST_MODIFICATION)); - info.pckg = stringFromCursor(info.pckg, cursor, Downloads.NOTIFICATION_PACKAGE); - info.clazz = stringFromCursor(info.clazz, cursor, Downloads.NOTIFICATION_CLASS); - info.cookies = stringFromCursor(info.cookies, cursor, Downloads.COOKIE_DATA); - info.userAgent = stringFromCursor(info.userAgent, cursor, Downloads.USER_AGENT); - info.referer = stringFromCursor(info.referer, cursor, Downloads.REFERER); - info.totalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.TOTAL_BYTES)); - info.currentBytes = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.CURRENT_BYTES)); - info.etag = stringFromCursor(info.etag, cursor, Constants.ETAG); - info.mediaScanned = + cursor.getInt(cursor.getColumnIndexOrThrow(Constants.RETRY_AFTER_X_REDIRECT_COUNT)); + info.mRetryAfter = retryRedirect & 0xfffffff; + info.mRedirectCount = retryRedirect >> 28; + info.mLastMod = cursor.getLong(cursor.getColumnIndexOrThrow( + Downloads.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.mTotalBytes = cursor.getInt(cursor.getColumnIndexOrThrow( + Downloads.COLUMN_TOTAL_BYTES)); + info.mCurrentBytes = cursor.getInt(cursor.getColumnIndexOrThrow( + Downloads.COLUMN_CURRENT_BYTES)); + info.mETag = stringFromCursor(info.mETag, cursor, Constants.ETAG); + info.mMediaScanned = cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) == 1; if (info.canUseNetwork(networkAvailable, networkRoaming)) { if (info.isReadyToRestart(now)) { if (Constants.LOGV) { Log.v(Constants.TAG, "Service spawning thread to handle updated download " + - info.id); + info.mId); } - if (info.hasActiveThread) { + if (info.mHasActiveThread) { throw new IllegalStateException("Multiple threads on same download on update"); } - info.status = Downloads.STATUS_RUNNING; + info.mStatus = Downloads.STATUS_RUNNING; ContentValues values = new ContentValues(); - values.put(Downloads.STATUS, info.status); + values.put(Downloads.COLUMN_STATUS, info.mStatus); getContentResolver().update( - ContentUris.withAppendedId(Downloads.CONTENT_URI, info.id), + ContentUris.withAppendedId(Downloads.CONTENT_URI, info.mId), values, null, null); DownloadThread downloader = new DownloadThread(this, info); - info.hasActiveThread = true; + info.mHasActiveThread = true; downloader.start(); } } @@ -756,11 +765,11 @@ public class DownloadService extends Service { if (old == null) { return cursor.getString(index); } - if (newChars == null) { - newChars = new CharArrayBuffer(128); + if (mNewChars == null) { + mNewChars = new CharArrayBuffer(128); } - cursor.copyStringToBuffer(index, newChars); - int length = newChars.sizeCopied; + cursor.copyStringToBuffer(index, mNewChars); + int length = mNewChars.sizeCopied; if (length != old.length()) { return cursor.getString(index); } @@ -768,7 +777,7 @@ public class DownloadService extends Service { oldChars = new CharArrayBuffer(length); } char[] oldArray = oldChars.data; - char[] newArray = newChars.data; + char[] newArray = mNewChars.data; old.getChars(0, length, oldArray, 0); for (int i = length - 1; i >= 0; --i) { if (oldArray[i] != newArray[i]) { @@ -783,12 +792,12 @@ public class DownloadService extends Service { */ private void deleteDownload(int arrayPos) { DownloadInfo info = (DownloadInfo) mDownloads.get(arrayPos); - if (info.status == Downloads.STATUS_RUNNING) { - info.status = Downloads.STATUS_CANCELED; - } else if (info.destination != Downloads.DESTINATION_EXTERNAL && info.filename != null) { - new File(info.filename).delete(); + if (info.mStatus == Downloads.STATUS_RUNNING) { + info.mStatus = Downloads.STATUS_CANCELED; + } else if (info.mDestination != Downloads.DESTINATION_EXTERNAL && info.mFileName != null) { + new File(info.mFileName).delete(); } - mNotifier.mNotificationMgr.cancel(info.id); + mNotifier.mNotificationMgr.cancel(info.mId); mDownloads.remove(arrayPos); } @@ -802,13 +811,13 @@ public class DownloadService extends Service { */ private long nextAction(int arrayPos, long now) { DownloadInfo info = (DownloadInfo) mDownloads.get(arrayPos); - if (Downloads.isStatusCompleted(info.status)) { + if (Downloads.isStatusCompleted(info.mStatus)) { return -1; } - if (info.status != Downloads.STATUS_RUNNING_PAUSED) { + if (info.mStatus != Downloads.STATUS_RUNNING_PAUSED) { return 0; } - if (info.numFailed == 0) { + if (info.mNumFailed == 0) { return 0; } long when = info.restartTime(); @@ -831,10 +840,10 @@ public class DownloadService extends Service { */ private boolean shouldScanFile(int arrayPos) { DownloadInfo info = (DownloadInfo) mDownloads.get(arrayPos); - return !info.mediaScanned - && info.destination == Downloads.DESTINATION_EXTERNAL - && Downloads.isStatusSuccess(info.status) - && !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(info.mimetype); + return !info.mMediaScanned + && info.mDestination == Downloads.DESTINATION_EXTERNAL + && Downloads.isStatusSuccess(info.mStatus) + && !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(info.mMimeType); } /** @@ -854,9 +863,9 @@ public class DownloadService extends Service { if (mMediaScannerService != null) { try { if (Constants.LOGV) { - Log.v(Constants.TAG, "Scanning file " + info.filename); + Log.v(Constants.TAG, "Scanning file " + info.mFileName); } - mMediaScannerService.scanFile(info.filename, info.mimetype); + mMediaScannerService.scanFile(info.mFileName, info.mMimeType); if (cursor != null) { ContentValues values = new ContentValues(); values.put(Constants.MEDIA_SCANNED, 1); @@ -868,7 +877,7 @@ public class DownloadService extends Service { return true; } catch (RemoteException e) { if (Config.LOGD) { - Log.d(Constants.TAG, "Failed to scan file " + info.filename); + Log.d(Constants.TAG, "Failed to scan file " + info.mFileName); } } } diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java index 3cc8c22b..d899314b 100644 --- a/src/com/android/providers/downloads/DownloadThread.java +++ b/src/com/android/providers/downloads/DownloadThread.java @@ -16,23 +16,19 @@ package com.android.providers.downloads; -import org.apache.http.client.methods.AbortableHttpRequest; +import org.apache.http.Header; +import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.HttpClient; import org.apache.http.entity.StringEntity; -import org.apache.http.Header; -import org.apache.http.HttpResponse; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import android.database.Cursor; import android.drm.mobile1.DrmRawContent; -import android.net.http.AndroidHttpClient; import android.net.Uri; +import android.net.http.AndroidHttpClient; import android.os.FileUtils; import android.os.PowerManager; import android.os.Process; @@ -42,12 +38,14 @@ import android.util.Config; import android.util.Log; import java.io.File; +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.InputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.io.InputStream; +import java.io.SyncFailedException; import java.net.URI; +import java.net.URISyntaxException; import java.util.Locale; /** @@ -67,7 +65,7 @@ public class DownloadThread extends Thread { * Returns the user agent provided by the initiating app, or use the default one */ private String userAgent() { - String userAgent = mInfo.userAgent; + String userAgent = mInfo.mUserAgent; if (userAgent != null) { } if (userAgent == null) { @@ -85,15 +83,15 @@ public class DownloadThread extends Thread { int finalStatus = Downloads.STATUS_UNKNOWN_ERROR; boolean countRetry = false; int retryAfter = 0; - int redirectCount = mInfo.redirectCount; + int redirectCount = mInfo.mRedirectCount; String newUri = null; boolean gotData = false; String filename = null; - String mimeType = sanitizeMimeType(mInfo.mimetype); + String mimeType = sanitizeMimeType(mInfo.mMimeType); FileOutputStream stream = null; AndroidHttpClient client = null; PowerManager.WakeLock wakeLock = null; - Uri contentUri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.id); + Uri contentUri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.mId); try { boolean continuingDownload = false; @@ -112,12 +110,12 @@ public class DownloadThread extends Thread { wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG); wakeLock.acquire(); - filename = mInfo.filename; + filename = mInfo.mFileName; if (filename != null) { if (!Helpers.isFilenameValid(filename)) { finalStatus = Downloads.STATUS_FILE_ERROR; notifyDownloadCompleted( - finalStatus, false, 0, 0, false, filename, null, mInfo.mimetype); + finalStatus, false, 0, 0, false, filename, null, mInfo.mMimeType); return; } // We're resuming a download that got interrupted @@ -128,7 +126,7 @@ public class DownloadThread extends Thread { // The download hadn't actually started, we can restart from scratch f.delete(); filename = null; - } else if (mInfo.etag == null && !mInfo.noIntegrity) { + } else if (mInfo.mETag == null && !mInfo.mNoIntegrity) { // Tough luck, that's not a resumable download if (Config.LOGD) { Log.d(Constants.TAG, @@ -137,16 +135,16 @@ public class DownloadThread extends Thread { f.delete(); finalStatus = Downloads.STATUS_PRECONDITION_FAILED; notifyDownloadCompleted( - finalStatus, false, 0, 0, false, filename, null, mInfo.mimetype); + finalStatus, false, 0, 0, false, filename, null, mInfo.mMimeType); return; } else { // All right, we'll be able to resume this download stream = new FileOutputStream(filename, true); bytesSoFar = (int) fileLength; - if (mInfo.totalBytes != -1) { - headerContentLength = Integer.toString(mInfo.totalBytes); + if (mInfo.mTotalBytes != -1) { + headerContentLength = Integer.toString(mInfo.mTotalBytes); } - headerETag = mInfo.etag; + headerETag = mInfo.mETag; continuingDownload = true; } } @@ -159,7 +157,7 @@ public class DownloadThread extends Thread { client = AndroidHttpClient.newInstance(userAgent()); - if (stream != null && mInfo.destination == Downloads.DESTINATION_EXTERNAL + if (stream != null && mInfo.mDestination == Downloads.DESTINATION_EXTERNAL && !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING .equalsIgnoreCase(mimeType)) { try { @@ -182,17 +180,17 @@ public class DownloadThread extends Thread { http_request_loop: while (true) { // Prepares the request and fires it. - HttpGet request = new HttpGet(mInfo.uri); + HttpGet request = new HttpGet(mInfo.mUri); if (Constants.LOGV) { - Log.v(Constants.TAG, "initiating download for " + mInfo.uri); + Log.v(Constants.TAG, "initiating download for " + mInfo.mUri); } - if (mInfo.cookies != null) { - request.addHeader("Cookie", mInfo.cookies); + if (mInfo.mCookies != null) { + request.addHeader("Cookie", mInfo.mCookies); } - if (mInfo.referer != null) { - request.addHeader("Referer", mInfo.referer); + if (mInfo.mReferer != null) { + request.addHeader("Referer", mInfo.mReferer); } if (continuingDownload) { if (headerETag != null) { @@ -207,27 +205,34 @@ http_request_loop: } catch (IllegalArgumentException ex) { if (Constants.LOGV) { Log.d(Constants.TAG, "Arg exception trying to execute request for " + - mInfo.uri + " : " + ex); + mInfo.mUri + " : " + ex); } else if (Config.LOGD) { Log.d(Constants.TAG, "Arg exception trying to execute request for " + - mInfo.id + " : " + ex); + mInfo.mId + " : " + ex); } finalStatus = Downloads.STATUS_BAD_REQUEST; request.abort(); break http_request_loop; } catch (IOException ex) { + if (Constants.LOGX) { + if (Helpers.isNetworkAvailable(mContext)) { + Log.i(Constants.TAG, "Execute Failed " + mInfo.mId + ", Net Up"); + } else { + Log.i(Constants.TAG, "Execute Failed " + mInfo.mId + ", Net Down"); + } + } if (!Helpers.isNetworkAvailable(mContext)) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; - } else if (mInfo.numFailed < Constants.MAX_RETRIES) { + } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; countRetry = true; } else { if (Constants.LOGV) { Log.d(Constants.TAG, "IOException trying to execute request for " + - mInfo.uri + " : " + ex); + mInfo.mUri + " : " + ex); } else if (Config.LOGD) { Log.d(Constants.TAG, "IOException trying to execute request for " + - mInfo.id + " : " + ex); + mInfo.mId + " : " + ex); } finalStatus = Downloads.STATUS_HTTP_DATA_ERROR; } @@ -236,7 +241,7 @@ http_request_loop: } int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode == 503 && mInfo.numFailed < Constants.MAX_RETRIES) { + if (statusCode == 503 && mInfo.mNumFailed < Constants.MAX_RETRIES) { if (Constants.LOGVV) { Log.v(Constants.TAG, "got HTTP response code 503"); } @@ -257,7 +262,7 @@ http_request_loop: } else if (retryAfter > Constants.MAX_RETRY_AFTER) { retryAfter = Constants.MAX_RETRY_AFTER; } - retryAfter += Helpers.rnd.nextInt(Constants.MIN_RETRY_AFTER + 1); + retryAfter += Helpers.sRandom.nextInt(Constants.MIN_RETRY_AFTER + 1); retryAfter *= 1000; } } catch (NumberFormatException ex) { @@ -276,10 +281,10 @@ http_request_loop: } if (redirectCount >= Constants.MAX_REDIRECTS) { if (Constants.LOGV) { - Log.d(Constants.TAG, "too many redirects for download " + mInfo.id + - " at " + mInfo.uri); + Log.d(Constants.TAG, "too many redirects for download " + mInfo.mId + + " at " + mInfo.mUri); } else if (Config.LOGD) { - Log.d(Constants.TAG, "too many redirects for download " + mInfo.id); + Log.d(Constants.TAG, "too many redirects for download " + mInfo.mId); } finalStatus = Downloads.STATUS_TOO_MANY_REDIRECTS; request.abort(); @@ -290,7 +295,26 @@ http_request_loop: if (Constants.LOGVV) { Log.v(Constants.TAG, "Location :" + header.getValue()); } - newUri = new URI(mInfo.uri).resolve(new URI(header.getValue())).toString(); + try { + newUri = new URI(mInfo.mUri). + resolve(new URI(header.getValue())). + toString(); + } catch(URISyntaxException ex) { + if (Constants.LOGV) { + Log.d(Constants.TAG, + "Couldn't resolve redirect URI " + + header.getValue() + + " for " + + mInfo.mUri); + } else if (Config.LOGD) { + Log.d(Constants.TAG, + "Couldn't resolve redirect URI for download " + + mInfo.mId); + } + finalStatus = Downloads.STATUS_BAD_REQUEST; + request.abort(); + break http_request_loop; + } ++redirectCount; finalStatus = Downloads.STATUS_RUNNING_PAUSED; request.abort(); @@ -300,10 +324,10 @@ http_request_loop: if ((!continuingDownload && statusCode != Downloads.STATUS_SUCCESS) || (continuingDownload && statusCode != 206)) { if (Constants.LOGV) { - Log.d(Constants.TAG, "http error " + statusCode + " for " + mInfo.uri); + Log.d(Constants.TAG, "http error " + statusCode + " for " + mInfo.mUri); } else if (Config.LOGD) { Log.d(Constants.TAG, "http error " + statusCode + " for download " + - mInfo.id); + mInfo.mId); } if (Downloads.isStatusError(statusCode)) { finalStatus = statusCode; @@ -319,7 +343,7 @@ http_request_loop: } else { // Handles the response, saves the file if (Constants.LOGV) { - Log.v(Constants.TAG, "received response for " + mInfo.uri); + Log.v(Constants.TAG, "received response for " + mInfo.mUri); } if (!continuingDownload) { @@ -372,7 +396,7 @@ http_request_loop: Log.v(Constants.TAG, "Transfer-Encoding: " + headerTransferEncoding); } - if (!mInfo.noIntegrity && headerContentLength == null && + if (!mInfo.mNoIntegrity && headerContentLength == null && (headerTransferEncoding == null || !headerTransferEncoding.equalsIgnoreCase("chunked")) ) { @@ -386,23 +410,23 @@ http_request_loop: DownloadFileInfo fileInfo = Helpers.generateSaveFile( mContext, - mInfo.uri, - mInfo.hint, + mInfo.mUri, + mInfo.mHint, headerContentDisposition, headerContentLocation, mimeType, - mInfo.destination, + mInfo.mDestination, (headerContentLength != null) ? Integer.parseInt(headerContentLength) : 0); - if (fileInfo.filename == null) { - finalStatus = fileInfo.status; + if (fileInfo.mFileName == null) { + finalStatus = fileInfo.mStatus; request.abort(); break http_request_loop; } - filename = fileInfo.filename; - stream = fileInfo.stream; + filename = fileInfo.mFileName; + stream = fileInfo.mStream; if (Constants.LOGV) { - Log.v(Constants.TAG, "writing " + mInfo.uri + " to " + filename); + Log.v(Constants.TAG, "writing " + mInfo.mUri + " to " + filename); } ContentValues values = new ContentValues(); @@ -411,13 +435,13 @@ http_request_loop: values.put(Constants.ETAG, headerETag); } if (mimeType != null) { - values.put(Downloads.MIMETYPE, mimeType); + values.put(Downloads.COLUMN_MIME_TYPE, mimeType); } int contentLength = -1; if (headerContentLength != null) { contentLength = Integer.parseInt(headerContentLength); } - values.put(Downloads.TOTAL_BYTES, contentLength); + values.put(Downloads.COLUMN_TOTAL_BYTES, contentLength); mContext.getContentResolver().update(contentUri, values, null, null); } @@ -425,18 +449,28 @@ http_request_loop: try { entityStream = response.getEntity().getContent(); } catch (IOException ex) { + if (Constants.LOGX) { + if (Helpers.isNetworkAvailable(mContext)) { + Log.i(Constants.TAG, "Get Failed " + mInfo.mId + ", Net Up"); + } else { + Log.i(Constants.TAG, "Get Failed " + mInfo.mId + ", Net Down"); + } + } if (!Helpers.isNetworkAvailable(mContext)) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; - } else if (mInfo.numFailed < Constants.MAX_RETRIES) { + } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; countRetry = true; } else { if (Constants.LOGV) { - Log.d(Constants.TAG, "IOException getting entity for " + mInfo.uri + - " : " + ex); + Log.d(Constants.TAG, + "IOException getting entity for " + + mInfo.mUri + + " : " + + ex); } else if (Config.LOGD) { Log.d(Constants.TAG, "IOException getting entity for download " + - mInfo.id + " : " + ex); + mInfo.mId + " : " + ex); } finalStatus = Downloads.STATUS_HTTP_DATA_ERROR; } @@ -448,16 +482,23 @@ http_request_loop: try { bytesRead = entityStream.read(data); } catch (IOException ex) { + if (Constants.LOGX) { + if (Helpers.isNetworkAvailable(mContext)) { + Log.i(Constants.TAG, "Read Failed " + mInfo.mId + ", Net Up"); + } else { + Log.i(Constants.TAG, "Read Failed " + mInfo.mId + ", Net Down"); + } + } ContentValues values = new ContentValues(); - values.put(Downloads.CURRENT_BYTES, bytesSoFar); + values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar); mContext.getContentResolver().update(contentUri, values, null, null); - if (!mInfo.noIntegrity && headerETag == null) { + if (!mInfo.mNoIntegrity && headerETag == null) { if (Constants.LOGV) { - Log.v(Constants.TAG, "download IOException for " + mInfo.uri + + Log.v(Constants.TAG, "download IOException for " + mInfo.mUri + " : " + ex); } else if (Config.LOGD) { Log.d(Constants.TAG, "download IOException for download " + - mInfo.id + " : " + ex); + mInfo.mId + " : " + ex); } if (Config.LOGD) { Log.d(Constants.TAG, @@ -466,16 +507,16 @@ http_request_loop: finalStatus = Downloads.STATUS_PRECONDITION_FAILED; } else if (!Helpers.isNetworkAvailable(mContext)) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; - } else if (mInfo.numFailed < Constants.MAX_RETRIES) { + } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; countRetry = true; } else { if (Constants.LOGV) { - Log.v(Constants.TAG, "download IOException for " + mInfo.uri + + Log.v(Constants.TAG, "download IOException for " + mInfo.mUri + " : " + ex); } else if (Config.LOGD) { Log.d(Constants.TAG, "download IOException for download " + - mInfo.id + " : " + ex); + mInfo.mId + " : " + ex); } finalStatus = Downloads.STATUS_HTTP_DATA_ERROR; } @@ -484,34 +525,34 @@ http_request_loop: } if (bytesRead == -1) { // success ContentValues values = new ContentValues(); - values.put(Downloads.CURRENT_BYTES, bytesSoFar); + values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar); if (headerContentLength == null) { - values.put(Downloads.TOTAL_BYTES, bytesSoFar); + values.put(Downloads.COLUMN_TOTAL_BYTES, bytesSoFar); } mContext.getContentResolver().update(contentUri, values, null, null); if ((headerContentLength != null) && (bytesSoFar != Integer.parseInt(headerContentLength))) { - if (!mInfo.noIntegrity && headerETag == null) { + if (!mInfo.mNoIntegrity && headerETag == null) { if (Constants.LOGV) { Log.d(Constants.TAG, "mismatched content length " + - mInfo.uri); + mInfo.mUri); } else if (Config.LOGD) { Log.d(Constants.TAG, "mismatched content length for " + - mInfo.id); + mInfo.mId); } finalStatus = Downloads.STATUS_LENGTH_REQUIRED; } else if (!Helpers.isNetworkAvailable(mContext)) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; - } else if (mInfo.numFailed < Constants.MAX_RETRIES) { + } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) { finalStatus = Downloads.STATUS_RUNNING_PAUSED; countRetry = true; } else { if (Constants.LOGV) { - Log.v(Constants.TAG, "closed socket for " + mInfo.uri); + Log.v(Constants.TAG, "closed socket for " + mInfo.mUri); } else if (Config.LOGD) { Log.d(Constants.TAG, "closed socket for download " + - mInfo.id); + mInfo.mId); } finalStatus = Downloads.STATUS_HTTP_DATA_ERROR; } @@ -526,7 +567,7 @@ http_request_loop: stream = new FileOutputStream(filename, true); } stream.write(data, 0, bytesRead); - if (mInfo.destination == Downloads.DESTINATION_EXTERNAL + if (mInfo.mDestination == Downloads.DESTINATION_EXTERNAL && !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING .equalsIgnoreCase(mimeType)) { try { @@ -556,7 +597,7 @@ http_request_loop: && now - timeLastNotification > Constants.MIN_PROGRESS_TIME) { ContentValues values = new ContentValues(); - values.put(Downloads.CURRENT_BYTES, bytesSoFar); + values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar); mContext.getContentResolver().update( contentUri, values, null, null); bytesNotified = bytesSoFar; @@ -564,30 +605,30 @@ http_request_loop: } if (Constants.LOGVV) { - Log.v(Constants.TAG, "downloaded " + bytesSoFar + " for " + mInfo.uri); + Log.v(Constants.TAG, "downloaded " + bytesSoFar + " for " + mInfo.mUri); } - synchronized(mInfo) { - if (mInfo.control == Downloads.CONTROL_PAUSED) { + synchronized (mInfo) { + if (mInfo.mControl == Downloads.CONTROL_PAUSED) { if (Constants.LOGV) { - Log.v(Constants.TAG, "paused " + mInfo.uri); + Log.v(Constants.TAG, "paused " + mInfo.mUri); } finalStatus = Downloads.STATUS_RUNNING_PAUSED; request.abort(); break http_request_loop; } } - if (mInfo.status == Downloads.STATUS_CANCELED) { + if (mInfo.mStatus == Downloads.STATUS_CANCELED) { if (Constants.LOGV) { - Log.d(Constants.TAG, "canceled " + mInfo.uri); + Log.d(Constants.TAG, "canceled " + mInfo.mUri); } else if (Config.LOGD) { - // Log.d(Constants.TAG, "canceled id " + mInfo.id); + // Log.d(Constants.TAG, "canceled id " + mInfo.mId); } finalStatus = Downloads.STATUS_CANCELED; break http_request_loop; } } if (Constants.LOGV) { - Log.v(Constants.TAG, "download completed for " + mInfo.uri); + Log.v(Constants.TAG, "download completed for " + mInfo.mUri); } finalStatus = Downloads.STATUS_SUCCESS; } @@ -599,16 +640,16 @@ http_request_loop: } finalStatus = Downloads.STATUS_FILE_ERROR; // falls through to the code that reports an error - } catch (Exception ex) { //sometimes the socket code throws unchecked exceptions + } catch (RuntimeException ex) { //sometimes the socket code throws unchecked exceptions if (Constants.LOGV) { - Log.d(Constants.TAG, "Exception for " + mInfo.uri, ex); + Log.d(Constants.TAG, "Exception for " + mInfo.mUri, ex); } else if (Config.LOGD) { - Log.d(Constants.TAG, "Exception for id " + mInfo.id, ex); + Log.d(Constants.TAG, "Exception for id " + mInfo.mId, ex); } finalStatus = Downloads.STATUS_UNKNOWN_ERROR; // falls through to the code that reports an error } finally { - mInfo.hasActiveThread = false; + mInfo.mHasActiveThread = false; if (wakeLock != null) { wakeLock.release(); wakeLock = null; @@ -651,6 +692,19 @@ http_request_loop: } else if (Downloads.isStatusSuccess(finalStatus)) { // make sure the file is readable FileUtils.setPermissions(filename, 0644, -1, -1); + + // Sync to storage after completion + try { + new FileOutputStream(filename, true).getFD().sync(); + } catch (FileNotFoundException ex) { + Log.w(Constants.TAG, "file " + filename + " not found: " + ex); + } catch (SyncFailedException ex) { + Log.w(Constants.TAG, "file " + filename + " sync failed: " + ex); + } catch (IOException ex) { + Log.w(Constants.TAG, "IOException trying to sync " + filename + ": " + ex); + } catch (RuntimeException ex) { + Log.w(Constants.TAG, "exception while syncing file: ", ex); + } } } notifyDownloadCompleted(finalStatus, countRetry, retryAfter, redirectCount, @@ -675,24 +729,24 @@ 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.STATUS, status); + values.put(Downloads.COLUMN_STATUS, status); values.put(Downloads._DATA, filename); if (uri != null) { - values.put(Downloads.URI, uri); + values.put(Downloads.COLUMN_URI, uri); } - values.put(Downloads.MIMETYPE, mimeType); - values.put(Downloads.LAST_MODIFICATION, System.currentTimeMillis()); - values.put(Constants.RETRY_AFTER___REDIRECT_COUNT, retryAfter + (redirectCount << 28)); + values.put(Downloads.COLUMN_MIME_TYPE, mimeType); + values.put(Downloads.COLUMN_LAST_MODIFICATION, System.currentTimeMillis()); + values.put(Constants.RETRY_AFTER_X_REDIRECT_COUNT, retryAfter + (redirectCount << 28)); if (!countRetry) { values.put(Constants.FAILED_CONNECTIONS, 0); } else if (gotData) { values.put(Constants.FAILED_CONNECTIONS, 1); } else { - values.put(Constants.FAILED_CONNECTIONS, mInfo.numFailed + 1); + values.put(Constants.FAILED_CONNECTIONS, mInfo.mNumFailed + 1); } mContext.getContentResolver().update( - ContentUris.withAppendedId(Downloads.CONTENT_URI, mInfo.id), values, null, null); + ContentUris.withAppendedId(Downloads.CONTENT_URI, mInfo.mId), values, null, null); } /** @@ -700,7 +754,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.id); + Uri uri = Uri.parse(Downloads.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 72be60ed..d8f262c7 100644 --- a/src/com/android/providers/downloads/Helpers.java +++ b/src/com/android/providers/downloads/Helpers.java @@ -38,18 +38,17 @@ import android.webkit.MimeTypeMap; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.util.List; import java.util.Random; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.Set; /** * Some helper functions for the download manager */ public class Helpers { - public static Random rnd = new Random(SystemClock.uptimeMillis()); + public static Random sRandom = new Random(SystemClock.uptimeMillis()); /** Regex used to parse content-disposition headers */ private static final Pattern CONTENT_DISPOSITION_PATTERN = @@ -411,7 +410,7 @@ public class Helpers { if (Constants.LOGVV) { Log.v(Constants.TAG, "file with sequence number " + sequence + " exists"); } - sequence += rnd.nextInt(magnitude) + 1; + sequence += sRandom.nextInt(magnitude) + 1; } } return null; @@ -427,11 +426,11 @@ public class Helpers { Downloads.CONTENT_URI, null, "( " + - Downloads.STATUS + " = '" + Downloads.STATUS_SUCCESS + "' AND " + - Downloads.DESTINATION + " = '" + Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE - + "' )", + Downloads.COLUMN_STATUS + " = '" + Downloads.STATUS_SUCCESS + "' AND " + + Downloads.COLUMN_DESTINATION + + " = '" + Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE + "' )", null, - Downloads.LAST_MODIFICATION); + Downloads.COLUMN_LAST_MODIFICATION); if (cursor == null) { return false; } @@ -755,7 +754,7 @@ public class Helpers { // quoted strings if (chars[mOffset] == '\'') { ++mOffset; - while(mOffset < chars.length) { + while (mOffset < chars.length) { if (chars[mOffset] == '\'') { if (mOffset + 1 < chars.length && chars[mOffset + 1] == '\'') { ++mOffset; -- cgit v1.2.3