Java 类android.provider.Downloads 实例源码
项目:SecureShareLib
文件:DownloadThread.java
/**
* Write a data buffer to the destination file.
* @param data buffer containing the data to write
* @param bytesRead how many bytes to write from the buffer
*/
private void writeDataToDestination(State state, byte[] data, int bytesRead, OutputStream out)
throws StopRequestException {
mStorageManager.verifySpaceBeforeWritingToFile(
mInfo.mDestination, state.mFilename, bytesRead);
boolean forceVerified = false;
while (true) {
try {
out.write(data, 0, bytesRead);
return;
} catch (IOException ex) {
// TODO: better differentiate between DRM and disk failures
if (!forceVerified) {
// couldn't write to file. are we out of space? check.
mStorageManager.verifySpace(mInfo.mDestination, state.mFilename, bytesRead);
forceVerified = true;
} else {
throw new StopRequestException(Downloads.Impl.STATUS_FILE_ERROR,
"Failed to write data: " + ex);
}
}
}
}
项目:SecureShareLib
文件:StorageManager.java
File locateDestinationDirectory(String mimeType, int destination, long contentLength)
throws StopRequestException {
switch (destination) {
case Downloads.Impl.DESTINATION_CACHE_PARTITION:
case Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE:
case Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING:
return mTransferDataDir;
case Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION:
return mSystemCacheDir;
case Downloads.Impl.DESTINATION_EXTERNAL:
File base = new File(mExternalStorageDir.getPath() + Constants.DEFAULT_DL_SUBDIR);
if (!base.isDirectory() && !base.mkdir()) {
// Can't create transfer directory, e.g. because a file called "transfer"
// already exists at the root level, or the SD card filesystem is read-only.
throw new StopRequestException(Downloads.Impl.STATUS_FILE_ERROR,
"unable to create external transfers directory " + base.getPath());
}
return base;
default:
throw new IllegalStateException("unexpected value for destination: " + destination);
}
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* Check that the file URI provided for DESTINATION_FILE_URI is valid.
*/
private void checkFileUriDestination(ContentValues values) {
String fileUri = values.getAsString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
if (fileUri == null) {
throw new IllegalArgumentException(
"DESTINATION_FILE_URI must include a file URI under COLUMN_FILE_NAME_HINT");
}
Uri uri = Uri.parse(fileUri);
String scheme = uri.getScheme();
if (scheme == null || !scheme.equals("file")) {
throw new IllegalArgumentException("Not a file URI: " + uri);
}
final String path = uri.getPath();
if (path == null) {
throw new IllegalArgumentException("Invalid file URI: " + uri);
}
try {
final String canonicalPath = new File(path).getCanonicalPath();
final String externalPath = Environment.getExternalStorageDirectory().getAbsolutePath();
if (!canonicalPath.startsWith(externalPath)) {
throw new SecurityException("Destination must be on external storage: " + uri);
}
} catch (IOException e) {
throw new SecurityException("Problem resolving path: " + uri);
}
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* Insert request headers for a transfer into the DB.
*/
private void insertRequestHeaders(SQLiteDatabase db, long transferId, ContentValues values) {
ContentValues rowValues = new ContentValues();
rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID, transferId);
for (Map.Entry<String, Object> entry : values.valueSet()) {
String key = entry.getKey();
if (key.startsWith(Downloads.Impl.RequestHeaders.INSERT_KEY_PREFIX)) {
String headerLine = entry.getValue().toString();
if (!headerLine.contains(":")) {
throw new IllegalArgumentException("Invalid HTTP header line: " + headerLine);
}
String[] parts = headerLine.split(":", 2);
rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_HEADER, parts[0].trim());
rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_VALUE, parts[1].trim());
db.insert(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, null, rowValues);
}
}
}
项目:SecureShareLib
文件:TransferProvider.java
private SqlSelection getWhereClause(final Uri uri, final String where, final String[] whereArgs,
int uriMatch) {
SqlSelection selection = new SqlSelection();
selection.appendClause(where, whereArgs);
if (uriMatch == MY_DOWNLOADS_ID || uriMatch == ALL_DOWNLOADS_ID ||
uriMatch == PUBLIC_DOWNLOAD_ID) {
selection.appendClause(Downloads.Impl._ID + " = ?", getTransferIdFromUri(uri));
}
if ((uriMatch == MY_DOWNLOADS || uriMatch == MY_DOWNLOADS_ID)
&& getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ALL)
!= PackageManager.PERMISSION_GRANTED) {
selection.appendClause(
Constants.UID + "= ? OR " + Downloads.Impl.COLUMN_OTHER_UID + "= ?",
Binder.getCallingUid(), Binder.getCallingUid());
}
return selection;
}
项目:SecureShareLib
文件:TransferInfo.java
private void readRequestHeaders(TransferInfo 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()) {
addHeader(info, cursor.getString(headerIndex), cursor.getString(valueIndex));
}
} finally {
cursor.close();
}
if (info.mCookies != null) {
addHeader(info, "Cookie", info.mCookies);
}
if (info.mReferer != null) {
addHeader(info, "Referer", info.mReferer);
}
}
项目:SecureShareLib
文件:TransferInfo.java
public void sendIntentIfRequested() {
if (mPackage == null) {
return;
}
Intent intent;
if (mIsPublicApi) {
intent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
intent.setPackage(mPackage);
intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, mId);
} else { // legacy behavior
if (mClass == null) {
return;
}
intent = new Intent(Downloads.Impl.ACTION_DOWNLOAD_COMPLETED);
intent.setClassName(mPackage, mClass);
if (mExtras != null) {
intent.putExtra(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, mExtras);
}
// We only send the content: URI, for security reasons. Otherwise, malicious
// applications would have an easier time spoofing transfer results by
// sending spoofed intents.
intent.setData(getMyDownloadsUri());
}
mSystemFacade.sendBroadcast(intent);
}
项目:SecureShareLib
文件:TransferInfo.java
/**
* Query and return status of requested transfer.
*/
public static int queryTransferStatus(ContentResolver resolver, long id) {
final Cursor cursor = resolver.query(
ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id),
new String[] { Downloads.Impl.COLUMN_STATUS }, null, null, null);
try {
if (cursor.moveToFirst()) {
return cursor.getInt(0);
} else {
// TODO: increase strictness of value returned for unknown
// transfers; this is safe default for now.
return Downloads.Impl.STATUS_PENDING;
}
} finally {
cursor.close();
}
}
项目:SecureShareLib
文件:TransferThread.java
/**
* Check if current connectivity is valid for this request.
*/
private void checkConnectivity() throws StopRequestException {
// checking connectivity will apply current policy
mPolicyDirty = false;
final NetworkState networkUsable = mInfo.checkCanUseNetwork();
if (networkUsable != NetworkState.OK) {
int status = Downloads.Impl.STATUS_WAITING_FOR_NETWORK;
if (networkUsable == NetworkState.UNUSABLE_DUE_TO_SIZE) {
status = Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
mInfo.notifyPauseDueToSize(true);
} else if (networkUsable == NetworkState.RECOMMENDED_UNUSABLE_DUE_TO_SIZE) {
status = Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
mInfo.notifyPauseDueToSize(false);
}
throw new StopRequestException(status, networkUsable.name());
}
}
项目:SecureShareLib
文件:TransferThread.java
/**
* Check if the transfer has been paused or canceled, stopping the request appropriately if it
* has been.
*/
private void checkPausedOrCanceled(State state) throws StopRequestException {
synchronized (mInfo) {
if (mInfo.mControl == Downloads.Impl.CONTROL_PAUSED) {
throw new StopRequestException(
Downloads.Impl.STATUS_PAUSED_BY_APP, "transfer paused by owner");
}
if (mInfo.mStatus == Downloads.Impl.STATUS_CANCELED || mInfo.mDeleted) {
throw new StopRequestException(Downloads.Impl.STATUS_CANCELED, "transfer canceled");
}
}
// if policy has been changed, trigger connectivity check
if (mPolicyDirty) {
checkConnectivity();
}
}
项目:SecureShareLib
文件:TransferThread.java
/**
* Called when we've reached the end of the HTTP response stream, to update the database and
* check for consistency.
*/
private void handleEndOfStream(State state) throws StopRequestException {
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, state.mCurrentBytes);
if (state.mContentLength == -1) {
values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, state.mCurrentBytes);
}
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);
final boolean lengthMismatched = (state.mContentLength != -1)
&& (state.mCurrentBytes != state.mContentLength);
if (lengthMismatched) {
if (cannotResume(state)) {
throw new StopRequestException(STATUS_CANNOT_RESUME,
"mismatched content length; unable to resume");
} else {
throw new StopRequestException(STATUS_HTTP_DATA_ERROR,
"closed socket before end of file");
}
}
}
项目:SecureShareLib
文件:TransferThread.java
/**
* Read some data from the HTTP response stream, handling I/O errors.
* @param data buffer to use to read data
* @param entityStream stream for reading the HTTP response entity
* @return the number of bytes actually read or -1 if the end of the stream has been reached
*/
private int readFromResponse(State state, byte[] data, InputStream entityStream)
throws StopRequestException {
try {
return entityStream.read(data);
} catch (IOException ex) {
// TODO: handle stream errors the same as other retries
if ("unexpected end of stream".equals(ex.getMessage())) {
return -1;
}
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, state.mCurrentBytes);
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);
if (cannotResume(state)) {
throw new StopRequestException(STATUS_CANNOT_RESUME,
"Failed reading response: " + ex + "; unable to resume", ex);
} else {
throw new StopRequestException(STATUS_HTTP_DATA_ERROR,
"Failed reading response: " + ex, ex);
}
}
}
项目:SecureShareLib
文件:TransferThread.java
private void notifyThroughDatabase(
State state, int finalStatus, String errorMsg, int numFailed) {
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_STATUS, finalStatus);
values.put(Downloads.Impl._DATA, state.mFilename);
values.put(Downloads.Impl.COLUMN_MIME_TYPE, state.mMimeType);
values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, mSystemFacade.currentTimeMillis());
values.put(Downloads.Impl.COLUMN_FAILED_CONNECTIONS, numFailed);
values.put(Constants.RETRY_AFTER_X_REDIRECT_COUNT, state.mRetryAfter);
if (!TextUtils.equals(mInfo.mUri, state.mRequestUri)) {
values.put(Downloads.Impl.COLUMN_URI, state.mRequestUri);
}
// save the error message. could be useful to developers.
if (!TextUtils.isEmpty(errorMsg)) {
values.put(Downloads.Impl.COLUMN_ERROR_MSG, errorMsg);
}
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);
}
项目:SecureShareLib
文件:SizeLimitActivity.java
private void showDialog(Cursor cursor) {
int size = cursor.getInt(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TOTAL_BYTES));
String sizeString = Formatter.formatFileSize(this, size);
String queueText = getString(R.string.button_queue_for_wifi);
boolean isWifiRequired =
mCurrentIntent.getExtras().getBoolean(TransferInfo.EXTRA_IS_WIFI_REQUIRED);
AlertDialog.Builder builder = new AlertDialog.Builder(this, AlertDialog.THEME_HOLO_DARK);
if (isWifiRequired) {
builder.setTitle(R.string.wifi_required_title)
.setMessage(getString(R.string.wifi_required_body, sizeString, queueText))
.setPositiveButton(R.string.button_queue_for_wifi, this)
.setNegativeButton(R.string.button_cancel_download, this);
} else {
builder.setTitle(R.string.wifi_recommended_title)
.setMessage(getString(R.string.wifi_recommended_body, sizeString, queueText))
.setPositiveButton(R.string.button_start_now, this)
.setNegativeButton(R.string.button_queue_for_wifi, this);
}
mDialog = builder.setOnCancelListener(this).show();
}
项目:SecureShareLib
文件:DownloadThread.java
/**
* Called just before the thread finishes, regardless of status, to take any necessary action on
* the transfered file.
*/
private void cleanupDestination(State state, int finalStatus) {
if (state.mFilename != null && Downloads.Impl.isStatusError(finalStatus)) {
if (Constants.LOGVV) {
Log.d(TAG, "cleanupDestination() deleting " + state.mFilename);
}
new File(state.mFilename).delete();
state.mFilename = null;
}
}
项目:SecureShareLib
文件:StorageManager.java
void verifySpace(int destination, String path, long length) throws StopRequestException {
resetBytesTransferedSinceLastCheckOnSpace();
File dir = null;
if (Constants.LOGV) {
Log.i(Constants.TAG, "in verifySpace, destination: " + destination +
", path: " + path + ", length: " + length);
}
if (path == null) {
throw new IllegalArgumentException("path can't be null");
}
switch (destination) {
case Downloads.Impl.DESTINATION_CACHE_PARTITION:
case Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING:
case Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE:
dir = mTransferDataDir;
break;
case Downloads.Impl.DESTINATION_EXTERNAL:
dir = mExternalStorageDir;
break;
case Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION:
dir = mSystemCacheDir;
break;
case Downloads.Impl.DESTINATION_FILE_URI:
if (path.startsWith(mExternalStorageDir.getPath())) {
dir = mExternalStorageDir;
} else if (path.startsWith(mTransferDataDir.getPath())) {
dir = mTransferDataDir;
} else if (path.startsWith(mSystemCacheDir.getPath())) {
dir = mSystemCacheDir;
}
break;
}
if (dir == null) {
throw new IllegalStateException("invalid combination of destination: " + destination +
", path: " + path);
}
findSpace(dir, length, destination);
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* insert() now ensures these four columns are never null for new transfers, so this method
* makes that true for existing columns, so that code can rely on this assumption.
*/
private void fillNullValues(SQLiteDatabase db) {
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, 0);
fillNullValuesForColumn(db, values);
values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, -1);
fillNullValuesForColumn(db, values);
values.put(Downloads.Impl.COLUMN_TITLE, "");
fillNullValuesForColumn(db, values);
values.put(Downloads.Impl.COLUMN_DESCRIPTION, "");
fillNullValuesForColumn(db, values);
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* Set all existing transfers to the cache partition to be invisible in the transfers UI.
*/
private void makeCacheDownloadsInvisible(SQLiteDatabase db) {
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, false);
String cacheSelection = Downloads.Impl.COLUMN_DESTINATION
+ " != " + Downloads.Impl.DESTINATION_EXTERNAL;
db.update(DB_TABLE, values, cacheSelection, null);
}
项目:SecureShareLib
文件:TransferProvider.java
private void createHeadersTable(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE);
db.execSQL("CREATE TABLE " + Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE + "(" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + " INTEGER NOT NULL," +
Downloads.Impl.RequestHeaders.COLUMN_HEADER + " TEXT NOT NULL," +
Downloads.Impl.RequestHeaders.COLUMN_VALUE + " TEXT NOT NULL" +
");");
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* Returns the content-provider-style MIME types of the various
* types accessible through this content provider.
*/
@Override
public String getType(final Uri uri) {
int match = sURIMatcher.match(uri);
switch (match) {
case MY_DOWNLOADS:
case ALL_DOWNLOADS: {
return DOWNLOAD_LIST_TYPE;
}
case MY_DOWNLOADS_ID:
case ALL_DOWNLOADS_ID:
case PUBLIC_DOWNLOAD_ID: {
// return the mimetype of this id from the database
final String id = getTransferIdFromUri(uri);
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
final String mimeType = DatabaseUtils.stringForQuery(db,
"SELECT " + Downloads.Impl.COLUMN_MIME_TYPE + " FROM " + DB_TABLE +
" WHERE " + Downloads.Impl._ID + " = ?",
new String[]{id});
if (TextUtils.isEmpty(mimeType)) {
return DOWNLOAD_TYPE;
} else {
return mimeType;
}
}
default: {
if (Constants.LOGV) {
Log.v(Constants.TAG, "calling getType on an unknown URI: " + uri);
}
throw new IllegalArgumentException("Unknown URI: " + uri);
}
}
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* Handle a query for the custom request headers registered for a transfer.
*/
private Cursor queryRequestHeaders(SQLiteDatabase db, Uri uri) {
String where = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "="
+ getTransferIdFromUri(uri);
String[] projection = new String[] {Downloads.Impl.RequestHeaders.COLUMN_HEADER,
Downloads.Impl.RequestHeaders.COLUMN_VALUE};
return db.query(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, projection, where,
null, null, null, null);
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* Delete request headers for transfers matching the given query.
*/
private void deleteRequestHeaders(SQLiteDatabase db, String where, String[] whereArgs) {
String[] projection = new String[] {Downloads.Impl._ID};
Cursor cursor = db.query(DB_TABLE, projection, where, whereArgs, null, null, null, null);
try {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
long id = cursor.getLong(0);
String idWhere = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "=" + id;
db.delete(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, idWhere, null);
}
} finally {
cursor.close();
}
}
项目:SecureShareLib
文件:TransferProvider.java
/**
* Deletes a row in the database
*/
@Override
public int delete(final Uri uri, final String where,
final String[] whereArgs) {
Helpers.validateSelection(where, sAppReadableColumnsSet);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
int match = sURIMatcher.match(uri);
switch (match) {
case MY_DOWNLOADS:
case MY_DOWNLOADS_ID:
case ALL_DOWNLOADS:
case ALL_DOWNLOADS_ID:
SqlSelection selection = getWhereClause(uri, where, whereArgs, match);
deleteRequestHeaders(db, selection.getSelection(), selection.getParameters());
final Cursor cursor = db.query(DB_TABLE, new String[] {
Downloads.Impl._ID }, selection.getSelection(), selection.getParameters(),
null, null, null);
try {
while (cursor.moveToNext()) {
final long id = cursor.getLong(0);
TransferStorageProvider.onTransferProviderDelete(getContext(), id);
}
} finally {
IoUtils.closeQuietly(cursor);
}
count = db.delete(DB_TABLE, selection.getSelection(), selection.getParameters());
break;
default:
Log.d(Constants.TAG, "deleting unknown/invalid URI: " + uri);
throw new UnsupportedOperationException("Cannot delete URI: " + uri);
}
notifyContentChanged(uri, match);
return count;
}
项目:SecureShareLib
文件:TransferProvider.java
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 120);
pw.println("Downloads updated in last hour:");
pw.increaseIndent();
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
final long modifiedAfter = mSystemFacade.currentTimeMillis() - DateUtils.HOUR_IN_MILLIS;
final Cursor cursor = db.query(DB_TABLE, null,
Downloads.Impl.COLUMN_LAST_MODIFICATION + ">" + modifiedAfter, null, null, null,
Downloads.Impl._ID + " ASC");
try {
final String[] cols = cursor.getColumnNames();
final int idCol = cursor.getColumnIndex(BaseColumns._ID);
while (cursor.moveToNext()) {
pw.println("Transfer #" + cursor.getInt(idCol) + ":");
pw.increaseIndent();
for (int i = 0; i < cols.length; i++) {
// Omit sensitive data when dumping
if (Downloads.Impl.COLUMN_COOKIE_DATA.equals(cols[i])) {
continue;
}
pw.printPair(cols[i], cursor.getString(i));
}
pw.println();
pw.decreaseIndent();
}
} finally {
cursor.close();
}
pw.decreaseIndent();
}
项目:SecureShareLib
文件:TransferProvider.java
private void logVerboseOpenFileInfo(Uri uri, String mode) {
Log.v(Constants.TAG, "openFile uri: " + uri + ", mode: " + mode
+ ", uid: " + Binder.getCallingUid());
Cursor cursor = query(Downloads.Impl.CONTENT_URI,
new String[] { "_id" }, null, null, "_id");
if (cursor == null) {
Log.v(Constants.TAG, "null cursor in openFile");
} else {
if (!cursor.moveToFirst()) {
Log.v(Constants.TAG, "empty cursor in openFile");
} else {
do {
Log.v(Constants.TAG, "row " + cursor.getInt(0) + " available");
} while(cursor.moveToNext());
}
cursor.close();
}
cursor = query(uri, new String[] { "_data" }, null, null, null);
if (cursor == null) {
Log.v(Constants.TAG, "null cursor in openFile");
} else {
if (!cursor.moveToFirst()) {
Log.v(Constants.TAG, "empty cursor in openFile");
} else {
String filename = cursor.getString(0);
Log.v(Constants.TAG, "filename in openFile: " + filename);
if (new java.io.File(filename).isFile()) {
Log.v(Constants.TAG, "file exists in openFile");
}
}
cursor.close();
}
}
项目:SecureShareLib
文件:TransferInfo.java
/**
* Returns whether this transfer should be enqueued.
*/
private boolean isReadyToTransfer() {
if (mControl == Downloads.Impl.CONTROL_PAUSED) {
// the transfer is paused, so it's not going to start
return false;
}
switch (mStatus) {
case 0: // status hasn't been initialized yet, this is a new transfer
case Downloads.Impl.STATUS_PENDING: // transfer is explicit marked as ready to start
case Downloads.Impl.STATUS_RUNNING: // transfer interrupted (process killed etc) while
// running, without a chance to update the database
return true;
case Downloads.Impl.STATUS_WAITING_FOR_NETWORK:
case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
return checkCanUseNetwork() == NetworkState.OK;
case Downloads.Impl.STATUS_WAITING_TO_RETRY:
// transfer was waiting for a delayed restart
final long now = mSystemFacade.currentTimeMillis();
return restartTime(now) <= now;
case Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR:
// is the media mounted?
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
case Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR:
// avoids repetition of retrying transfer
return false;
}
return false;
}
项目:SecureShareLib
文件:TransferInfo.java
/**
* Returns whether this transfer has a visible notification after
* completion.
*/
public boolean hasCompletionNotification() {
if (!Downloads.Impl.isStatusCompleted(mStatus)) {
return false;
}
if (mVisibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
return true;
}
return false;
}
项目:SecureShareLib
文件:TransferInfo.java
private boolean isRoamingAllowed() {
if (mIsPublicApi) {
return mAllowRoaming;
} else { // legacy behavior
return mDestination != Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING;
}
}
项目:SecureShareLib
文件:TransferInfo.java
/**
* Return time when this transfer will be ready for its next action, in
* milliseconds after given time.
*
* @return If {@code 0}, transfer is ready to proceed immediately. If
* {@link Long#MAX_VALUE}, then transfer has no future actions.
*/
public long nextActionMillis(long now) {
if (Downloads.Impl.isStatusCompleted(mStatus)) {
return Long.MAX_VALUE;
}
if (mStatus != Downloads.Impl.STATUS_WAITING_TO_RETRY) {
return 0;
}
long when = restartTime(now);
if (when <= now) {
return 0;
}
return when - now;
}
项目:SecureShareLib
文件:TransferInfo.java
/**
* Returns whether a file should be scanned
*/
public boolean shouldScanFile() {
return (mMediaScanned == 0)
&& (mDestination == Downloads.Impl.DESTINATION_EXTERNAL ||
mDestination == Downloads.Impl.DESTINATION_FILE_URI ||
mDestination == Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD)
&& Downloads.Impl.isStatusSuccess(mStatus);
}
项目:SecureShareLib
文件:TransferReceiver.java
/**
* Mark the given {@link TransferManager#COLUMN_ID} as being acknowledged by
* user so it's not renewed later.
*/
private void hideNotification(Context context, long id) {
final int status;
final int visibility;
final Uri uri = ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id);
final Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
try {
if (cursor.moveToFirst()) {
status = getInt(cursor, Downloads.Impl.COLUMN_STATUS);
visibility = getInt(cursor, Downloads.Impl.COLUMN_VISIBILITY);
} else {
Log.w(TAG, "Missing details for transfer " + id);
return;
}
} finally {
cursor.close();
}
if (Downloads.Impl.isStatusCompleted(status) &&
(visibility == VISIBILITY_VISIBLE_NOTIFY_COMPLETED
|| visibility == VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION)) {
final ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_VISIBILITY,
Downloads.Impl.VISIBILITY_VISIBLE);
context.getContentResolver().update(uri, values, null, null);
}
}
项目:SecureShareLib
文件:Helpers.java
/**
* Creates a filename (where the file should be saved) from info about a transfer.
*/
static String generateSaveFile(
Context context,
String url,
String hint,
String contentDisposition,
String contentLocation,
String mimeType,
int destination,
long contentLength,
StorageManager storageManager) throws StopRequestException {
if (contentLength < 0) {
contentLength = 0;
}
String path;
File base = null;
if (destination == Downloads.Impl.DESTINATION_FILE_URI) {
path = Uri.parse(hint).getPath();
} else {
base = storageManager.locateDestinationDirectory(mimeType, destination,
contentLength);
path = chooseFilename(url, hint, contentDisposition, contentLocation,
destination);
}
storageManager.verifySpace(destination, path, contentLength);
if (TransferDrmHelper.isDrmConvertNeeded(mimeType)) {
path = TransferDrmHelper.modifyDrmFwLockFileExtension(path);
}
path = getFullPath(path, mimeType, destination, base);
return path;
}
项目:SecureShareLib
文件:TransferScanner.java
@Override
public void onScanCompleted(String path, Uri uri) {
final ScanRequest req;
synchronized (mConnection) {
req = mPending.remove(path);
}
if (req == null) {
Log.w(TAG, "Missing request for path " + path);
return;
}
// Update scanned column, which will kick off a database update pass,
// eventually deciding if overall service is ready for teardown.
final ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_MEDIA_SCANNED, 1);
if (uri != null) {
values.put(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI, uri.toString());
}
final ContentResolver resolver = mContext.getContentResolver();
final Uri transferUri = ContentUris.withAppendedId(
Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, req.id);
final int rows = resolver.update(transferUri, values, null, null);
if (rows == 0) {
// Local row disappeared during scan; transfer was probably deleted
// so clean up now-orphaned media entry.
resolver.delete(uri, null, null);
}
}
项目:SecureShareLib
文件:TransferThread.java
/**
* Report transfer progress through the database if necessary.
*/
private void reportProgress(State state) {
final long now = SystemClock.elapsedRealtime();
final long sampleDelta = now - state.mSpeedSampleStart;
if (sampleDelta > 500) {
final long sampleSpeed = ((state.mCurrentBytes - state.mSpeedSampleBytes) * 1000)
/ sampleDelta;
if (state.mSpeed == 0) {
state.mSpeed = sampleSpeed;
} else {
state.mSpeed = ((state.mSpeed * 3) + sampleSpeed) / 4;
}
// Only notify once we have a full sample window
if (state.mSpeedSampleStart != 0) {
mNotifier.notifyTransferSpeed(mInfo.mId, state.mSpeed);
}
state.mSpeedSampleStart = now;
state.mSpeedSampleBytes = state.mCurrentBytes;
}
if (state.mCurrentBytes - state.mBytesNotified > Constants.MIN_PROGRESS_STEP &&
now - state.mTimeLastNotification > Constants.MIN_PROGRESS_TIME) {
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, state.mCurrentBytes);
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);
state.mBytesNotified = state.mCurrentBytes;
state.mTimeLastNotification = now;
}
}
项目:SecureShareLib
文件:TransferThread.java
/**
* Update necessary database fields based on values of HTTP response headers that have been
* read.
*/
private void updateDatabaseFromHeaders(State state) {
ContentValues values = new ContentValues();
values.put(Downloads.Impl._DATA, state.mFilename);
if (state.mHeaderETag != null) {
values.put(Constants.ETAG, state.mHeaderETag);
}
if (state.mMimeType != null) {
values.put(Downloads.Impl.COLUMN_MIME_TYPE, state.mMimeType);
}
values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, mInfo.mTotalBytes);
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);
}
项目:SecureShareLib
文件:TransferThread.java
/**
* Stores information about the completed transfer, and notifies the initiating application.
*/
private void notifyTransferCompleted(
State state, int finalStatus, String errorMsg, int numFailed) {
notifyThroughDatabase(state, finalStatus, errorMsg, numFailed);
if (Downloads.Impl.isStatusCompleted(finalStatus)) {
mInfo.sendIntentIfRequested();
}
}
项目:SecureShareLib
文件:TransferService.java
/**
* Initializes the service when it is first created
*/
@Override
public void onCreate() {
super.onCreate();
if (Constants.LOGVV) {
Log.v(Constants.TAG, "Service onCreate");
}
if (mSystemFacade == null) {
mSystemFacade = new RealSystemFacade(this);
}
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mStorageManager = new StorageManager(this);
mUpdateThread = new HandlerThread(TAG + "-UpdateThread");
mUpdateThread.start();
mUpdateHandler = new Handler(mUpdateThread.getLooper(), mUpdateCallback);
mScanner = new TransferScanner(this);
mNotifier = new TransferNotifier(this);
mNotifier.cancelAll();
mObserver = new TransferManagerContentObserver();
getContentResolver().registerContentObserver(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
true, mObserver);
}
项目:SecureShareLib
文件:TransferService.java
/**
* Removes the local copy of the info about a transfer.
*/
private void deleteTransferLocked(long id) {
TransferInfo info = mTransfers.get(id);
if (info.mStatus == Downloads.Impl.STATUS_RUNNING) {
info.mStatus = Downloads.Impl.STATUS_CANCELED;
}
if (info.mDestination != Downloads.Impl.DESTINATION_EXTERNAL && info.mFileName != null) {
if (Constants.LOGVV) {
Log.d(TAG, "deleteTransferLocked() deleting " + info.mFileName);
}
deleteFileIfExists(info.mFileName);
}
mTransfers.remove(info.mId);
}
项目:SecureShareLib
文件:TransferNotifier.java
/**
* Build tag used for collapsing several {@link TransferInfo} into a single
* {@link Notification}.
*/
private static String buildNotificationTag(TransferInfo info) {
if (info.mStatus == Downloads.Impl.STATUS_QUEUED_FOR_WIFI) {
return TYPE_WAITING + ":" + info.mPackage;
} else if (isActiveAndVisible(info)) {
return TYPE_ACTIVE + ":" + info.mPackage;
} else if (isCompleteAndVisible(info)) {
// Complete transfers always have unique notifs
return TYPE_COMPLETE + ":" + info.mId;
} else {
return null;
}
}
项目:SecureShareLib
文件:DownloadThread.java
/**
* Prepare the destination file to receive data. If the file already exists, we'll set up
* appropriately for resumption.
*/
private void setupDestinationFile(State state) throws StopRequestException {
if (!TextUtils.isEmpty(state.mFilename)) { // only true if we've already run a thread for this transfer
if (Constants.LOGV) {
Log.i(Constants.TAG, "have run thread before for id: " + mInfo.mId +
", and state.mFilename: " + state.mFilename);
}
if (!Helpers.isFilenameValid(state.mFilename,
mStorageManager.getTransferDataDirectory())) {
// this should never happen
throw new StopRequestException(Downloads.Impl.STATUS_FILE_ERROR,
"found invalid internal destination filename");
}
// We're resuming a transfer that got interrupted
File f = new File(state.mFilename);
if (f.exists()) {
if (Constants.LOGV) {
Log.i(Constants.TAG, "resuming transfer for id: " + mInfo.mId +
", and state.mFilename: " + state.mFilename);
}
long fileLength = f.length();
if (fileLength == 0) {
// The transfer hadn't actually started, we can restart from scratch
if (Constants.LOGVV) {
Log.d(TAG, "setupDestinationFile() found fileLength=0, deleting "
+ state.mFilename);
}
f.delete();
state.mFilename = null;
if (Constants.LOGV) {
Log.i(Constants.TAG, "resuming transfer for id: " + mInfo.mId +
", BUT starting from scratch again: ");
}
} else if (mInfo.mETag == null && !mInfo.mNoIntegrity) {
// This should've been caught upon failure
if (Constants.LOGVV) {
Log.d(TAG, "setupDestinationFile() unable to resume transfer, deleting "
+ state.mFilename);
}
f.delete();
throw new StopRequestException(Downloads.Impl.STATUS_CANNOT_RESUME,
"Trying to resume a transfer that can't be resumed");
} else {
// All right, we'll be able to resume this transfer
if (Constants.LOGV) {
Log.i(Constants.TAG, "resuming transfer for id: " + mInfo.mId +
", and starting with file of length: " + fileLength);
}
state.mCurrentBytes = (int) fileLength;
if (mInfo.mTotalBytes != -1) {
state.mContentLength = mInfo.mTotalBytes;
}
state.mHeaderETag = mInfo.mETag;
state.mContinuingTransfer = true;
if (Constants.LOGV) {
Log.i(Constants.TAG, "resuming transfer for id: " + mInfo.mId +
", state.mCurrentBytes: " + state.mCurrentBytes +
", and setting mContinuingTransfer to true: ");
}
}
}
}
}