summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/DownloadInfo.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers/downloads/DownloadInfo.java')
-rw-r--r--src/com/android/providers/downloads/DownloadInfo.java264
1 files changed, 188 insertions, 76 deletions
diff --git a/src/com/android/providers/downloads/DownloadInfo.java b/src/com/android/providers/downloads/DownloadInfo.java
index 0cf025b8..eb9ac4bd 100644
--- a/src/com/android/providers/downloads/DownloadInfo.java
+++ b/src/com/android/providers/downloads/DownloadInfo.java
@@ -16,11 +16,14 @@
package com.android.providers.downloads;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.database.CharArrayBuffer;
import android.database.Cursor;
+import android.drm.mobile1.DrmRawContent;
import android.net.ConnectivityManager;
import android.net.DownloadManager;
import android.net.Uri;
@@ -36,7 +39,127 @@ import java.util.Map;
* Stores information about an individual download.
*/
public class DownloadInfo {
- public int mId;
+ public static class Reader {
+ private ContentResolver mResolver;
+ private Cursor mCursor;
+ private CharArrayBuffer mOldChars;
+ private CharArrayBuffer mNewChars;
+
+ public Reader(ContentResolver resolver, Cursor cursor) {
+ mResolver = resolver;
+ mCursor = cursor;
+ }
+
+ public DownloadInfo newDownloadInfo(Context context, SystemFacade systemFacade) {
+ DownloadInfo info = new DownloadInfo(context, systemFacade);
+ updateFromDatabase(info);
+ readRequestHeaders(info);
+ return info;
+ }
+
+ public void updateFromDatabase(DownloadInfo info) {
+ info.mId = getLong(Downloads.Impl._ID);
+ info.mUri = getString(info.mUri, Downloads.Impl.COLUMN_URI);
+ info.mNoIntegrity = getInt(Downloads.Impl.COLUMN_NO_INTEGRITY) == 1;
+ info.mHint = getString(info.mHint, Downloads.Impl.COLUMN_FILE_NAME_HINT);
+ info.mFileName = getString(info.mFileName, Downloads.Impl._DATA);
+ info.mMimeType = getString(info.mMimeType, Downloads.Impl.COLUMN_MIME_TYPE);
+ info.mDestination = getInt(Downloads.Impl.COLUMN_DESTINATION);
+ info.mVisibility = getInt(Downloads.Impl.COLUMN_VISIBILITY);
+ info.mStatus = getInt(Downloads.Impl.COLUMN_STATUS);
+ info.mNumFailed = getInt(Constants.FAILED_CONNECTIONS);
+ int retryRedirect = getInt(Constants.RETRY_AFTER_X_REDIRECT_COUNT);
+ info.mRetryAfter = retryRedirect & 0xfffffff;
+ info.mRedirectCount = retryRedirect >> 28;
+ info.mLastMod = getLong(Downloads.Impl.COLUMN_LAST_MODIFICATION);
+ info.mPackage = getString(info.mPackage, Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
+ info.mClass = getString(info.mClass, Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
+ info.mExtras = getString(info.mExtras, Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS);
+ info.mCookies = getString(info.mCookies, Downloads.Impl.COLUMN_COOKIE_DATA);
+ info.mUserAgent = getString(info.mUserAgent, Downloads.Impl.COLUMN_USER_AGENT);
+ info.mReferer = getString(info.mReferer, Downloads.Impl.COLUMN_REFERER);
+ info.mTotalBytes = getLong(Downloads.Impl.COLUMN_TOTAL_BYTES);
+ info.mCurrentBytes = getLong(Downloads.Impl.COLUMN_CURRENT_BYTES);
+ info.mETag = getString(info.mETag, Constants.ETAG);
+ info.mMediaScanned = getInt(Constants.MEDIA_SCANNED) == 1;
+ info.mIsPublicApi = getInt(Downloads.Impl.COLUMN_IS_PUBLIC_API) != 0;
+ info.mAllowedNetworkTypes = getInt(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES);
+ info.mAllowRoaming = getInt(Downloads.Impl.COLUMN_ALLOW_ROAMING) != 0;
+ info.mTitle = getString(info.mTitle, Downloads.Impl.COLUMN_TITLE);
+ info.mDescription = getString(info.mDescription, Downloads.Impl.COLUMN_DESCRIPTION);
+
+ synchronized (this) {
+ info.mControl = getInt(Downloads.Impl.COLUMN_CONTROL);
+ }
+ }
+
+ private void readRequestHeaders(DownloadInfo info) {
+ info.mRequestHeaders.clear();
+ Uri headerUri = Uri.withAppendedPath(
+ info.getAllDownloadsUri(), Downloads.Impl.RequestHeaders.URI_SEGMENT);
+ Cursor cursor = mResolver.query(headerUri, null, null, null, null);
+ try {
+ int headerIndex =
+ cursor.getColumnIndexOrThrow(Downloads.Impl.RequestHeaders.COLUMN_HEADER);
+ int valueIndex =
+ cursor.getColumnIndexOrThrow(Downloads.Impl.RequestHeaders.COLUMN_VALUE);
+ for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
+ info.mRequestHeaders.put(
+ cursor.getString(headerIndex), cursor.getString(valueIndex));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ if (info.mCookies != null) {
+ info.mRequestHeaders.put("Cookie", info.mCookies);
+ }
+ if (info.mReferer != null) {
+ info.mRequestHeaders.put("Referer", info.mReferer);
+ }
+ }
+
+ /**
+ * Returns a String that holds the current value of the column, optimizing for the case
+ * where the value hasn't changed.
+ */
+ private String getString(String old, String column) {
+ int index = mCursor.getColumnIndexOrThrow(column);
+ if (old == null) {
+ return mCursor.getString(index);
+ }
+ if (mNewChars == null) {
+ mNewChars = new CharArrayBuffer(128);
+ }
+ mCursor.copyStringToBuffer(index, mNewChars);
+ int length = mNewChars.sizeCopied;
+ if (length != old.length()) {
+ return new String(mNewChars.data, 0, length);
+ }
+ if (mOldChars == null || mOldChars.sizeCopied < length) {
+ mOldChars = new CharArrayBuffer(length);
+ }
+ char[] oldArray = mOldChars.data;
+ char[] newArray = mNewChars.data;
+ old.getChars(0, length, oldArray, 0);
+ for (int i = length - 1; i >= 0; --i) {
+ if (oldArray[i] != newArray[i]) {
+ return new String(newArray, 0, length);
+ }
+ }
+ return old;
+ }
+
+ private Integer getInt(String column) {
+ return mCursor.getInt(mCursor.getColumnIndexOrThrow(column));
+ }
+
+ private Long getLong(String column) {
+ return mCursor.getLong(mCursor.getColumnIndexOrThrow(column));
+ }
+ }
+
+ public long mId;
public String mUri;
public boolean mNoIntegrity;
public String mHint;
@@ -75,83 +198,10 @@ public class DownloadInfo {
private SystemFacade mSystemFacade;
private Context mContext;
- public DownloadInfo(Context context, SystemFacade systemFacade, Cursor cursor) {
+ private DownloadInfo(Context context, SystemFacade systemFacade) {
mContext = context;
mSystemFacade = systemFacade;
-
- int retryRedirect =
- cursor.getInt(cursor.getColumnIndexOrThrow(Constants.RETRY_AFTER_X_REDIRECT_COUNT));
- mId = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl._ID));
- mUri = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_URI));
- mNoIntegrity = cursor.getInt(cursor.getColumnIndexOrThrow(
- Downloads.Impl.COLUMN_NO_INTEGRITY)) == 1;
- mHint = cursor.getString(cursor.getColumnIndexOrThrow(
- Downloads.Impl.COLUMN_FILE_NAME_HINT));
- mFileName = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl._DATA));
- mMimeType = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_MIME_TYPE));
- mDestination =
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESTINATION));
- mVisibility = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_VISIBILITY));
- mControl = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_CONTROL));
- mStatus = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS));
- mNumFailed = cursor.getInt(cursor.getColumnIndexOrThrow(Constants.FAILED_CONNECTIONS));
- mRetryAfter = retryRedirect & 0xfffffff;
- mRedirectCount = retryRedirect >> 28;
- mLastMod = cursor.getLong(cursor.getColumnIndexOrThrow(
- Downloads.Impl.COLUMN_LAST_MODIFICATION));
- mPackage = cursor.getString(cursor.getColumnIndexOrThrow(
- Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE));
- mClass = cursor.getString(cursor.getColumnIndexOrThrow(
- Downloads.Impl.COLUMN_NOTIFICATION_CLASS));
- mExtras = cursor.getString(cursor.getColumnIndexOrThrow(
- Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS));
- mCookies =
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_COOKIE_DATA));
- mUserAgent =
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_USER_AGENT));
- mReferer = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_REFERER));
- mTotalBytes =
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TOTAL_BYTES));
- mCurrentBytes =
- cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_CURRENT_BYTES));
- mETag = cursor.getString(cursor.getColumnIndexOrThrow(Constants.ETAG));
- mMediaScanned = cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) == 1;
- mIsPublicApi = cursor.getInt(
- cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_IS_PUBLIC_API)) != 0;
- mAllowedNetworkTypes = cursor.getInt(
- cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES));
- mAllowRoaming = cursor.getInt(
- cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_ALLOW_ROAMING)) != 0;
- mTitle = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE));
- mDescription =
- cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESCRIPTION));
mFuzz = Helpers.sRandom.nextInt(1001);
-
- readRequestHeaders(mId);
- }
-
- private void readRequestHeaders(long downloadId) {
- Uri headerUri = Uri.withAppendedPath(
- getAllDownloadsUri(), Downloads.Impl.RequestHeaders.URI_SEGMENT);
- Cursor cursor = mContext.getContentResolver().query(headerUri, null, null, null, null);
- try {
- int headerIndex =
- cursor.getColumnIndexOrThrow(Downloads.Impl.RequestHeaders.COLUMN_HEADER);
- int valueIndex =
- cursor.getColumnIndexOrThrow(Downloads.Impl.RequestHeaders.COLUMN_VALUE);
- for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
- mRequestHeaders.put(cursor.getString(headerIndex), cursor.getString(valueIndex));
- }
- } finally {
- cursor.close();
- }
-
- if (mCookies != null) {
- mRequestHeaders.put("Cookie", mCookies);
- }
- if (mReferer != null) {
- mRequestHeaders.put("Referer", mReferer);
- }
}
public Map<String, String> getHeaders() {
@@ -167,7 +217,7 @@ public class DownloadInfo {
if (mIsPublicApi) {
intent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
intent.setPackage(mPackage);
- intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, (long) mId);
+ intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, mId);
} else { // legacy behavior
if (mClass == null) {
return;
@@ -393,4 +443,66 @@ public class DownloadInfo {
public Uri getAllDownloadsUri() {
return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, mId);
}
+
+
+ public void logVerboseInfo() {
+ Log.v(Constants.TAG, "Service adding new entry");
+ Log.v(Constants.TAG, "ID : " + mId);
+ Log.v(Constants.TAG, "URI : " + ((mUri != null) ? "yes" : "no"));
+ Log.v(Constants.TAG, "NO_INTEG: " + mNoIntegrity);
+ Log.v(Constants.TAG, "HINT : " + mHint);
+ Log.v(Constants.TAG, "FILENAME: " + mFileName);
+ Log.v(Constants.TAG, "MIMETYPE: " + mMimeType);
+ Log.v(Constants.TAG, "DESTINAT: " + mDestination);
+ Log.v(Constants.TAG, "VISIBILI: " + mVisibility);
+ Log.v(Constants.TAG, "CONTROL : " + mControl);
+ Log.v(Constants.TAG, "STATUS : " + mStatus);
+ Log.v(Constants.TAG, "FAILED_C: " + mNumFailed);
+ Log.v(Constants.TAG, "RETRY_AF: " + mRetryAfter);
+ Log.v(Constants.TAG, "REDIRECT: " + mRedirectCount);
+ Log.v(Constants.TAG, "LAST_MOD: " + mLastMod);
+ Log.v(Constants.TAG, "PACKAGE : " + mPackage);
+ Log.v(Constants.TAG, "CLASS : " + mClass);
+ Log.v(Constants.TAG, "COOKIES : " + ((mCookies != null) ? "yes" : "no"));
+ Log.v(Constants.TAG, "AGENT : " + mUserAgent);
+ Log.v(Constants.TAG, "REFERER : " + ((mReferer != null) ? "yes" : "no"));
+ Log.v(Constants.TAG, "TOTAL : " + mTotalBytes);
+ Log.v(Constants.TAG, "CURRENT : " + mCurrentBytes);
+ Log.v(Constants.TAG, "ETAG : " + mETag);
+ Log.v(Constants.TAG, "SCANNED : " + mMediaScanned);
+ }
+
+ /**
+ * Returns the amount of time (as measured from the "now" parameter)
+ * at which a download will be active.
+ * 0 = immediately - service should stick around to handle this download.
+ * -1 = never - service can go away without ever waking up.
+ * positive value - service must wake up in the future, as specified in ms from "now"
+ */
+ long nextAction(long now) {
+ if (Downloads.Impl.isStatusCompleted(mStatus)) {
+ return -1;
+ }
+ if (mStatus != Downloads.Impl.STATUS_RUNNING_PAUSED) {
+ return 0;
+ }
+ if (mNumFailed == 0) {
+ return 0;
+ }
+ long when = restartTime();
+ if (when <= now) {
+ return 0;
+ }
+ return when - now;
+ }
+
+ /**
+ * Returns whether a file should be scanned
+ */
+ boolean shouldScanFile() {
+ return !mMediaScanned
+ && mDestination == Downloads.Impl.DESTINATION_EXTERNAL
+ && Downloads.Impl.isStatusSuccess(mStatus)
+ && !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(mMimeType);
+ }
}