diff options
Diffstat (limited to 'src/com/android/providers/downloads/DownloadService.java')
-rw-r--r-- | src/com/android/providers/downloads/DownloadService.java | 121 |
1 files changed, 77 insertions, 44 deletions
diff --git a/src/com/android/providers/downloads/DownloadService.java b/src/com/android/providers/downloads/DownloadService.java index 169ef970..f93c5c2e 100644 --- a/src/com/android/providers/downloads/DownloadService.java +++ b/src/com/android/providers/downloads/DownloadService.java @@ -28,6 +28,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.database.ContentObserver; import android.database.Cursor; +import android.database.sqlite.SQLiteException; import android.media.IMediaScannerListener; import android.media.IMediaScannerService; import android.net.Uri; @@ -44,7 +45,6 @@ import com.google.android.collect.Maps; import com.google.common.annotations.VisibleForTesting; import java.io.File; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -114,6 +114,7 @@ public class DownloadService extends Service { * Receives notification when the data in the observed content * provider changes. */ + @Override public void onChange(final boolean selfChange) { if (Constants.LOGVV) { Log.v(Constants.TAG, "Service ContentObserver received notification"); @@ -188,6 +189,7 @@ public class DownloadService extends Service { * * @throws UnsupportedOperationException */ + @Override public IBinder onBind(Intent i) { throw new UnsupportedOperationException("Cannot bind to Download Manager Service"); } @@ -195,6 +197,7 @@ public class DownloadService extends Service { /** * Initializes the service when it is first created */ + @Override public void onCreate() { super.onCreate(); if (Constants.LOGVV) { @@ -232,6 +235,7 @@ public class DownloadService extends Service { /** * Cleans up when the service is destroyed */ + @Override public void onDestroy() { getContentResolver().unregisterContentObserver(mObserver); if (Constants.LOGVV) { @@ -258,6 +262,7 @@ public class DownloadService extends Service { super("Download Service"); } + @Override public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); @@ -363,24 +368,23 @@ public class DownloadService extends Service { if (info.shouldScanFile()) { // initiate rescan of the file to - which will populate // mediaProviderUri column in this row - if (!scanFile(info, true, false)) { + if (!scanFile(info, false, true)) { throw new IllegalStateException("scanFile failed!"); } - } else { - // this file should NOT be scanned. delete the file. - Helpers.deleteFile(getContentResolver(), info.mId, info.mFileName, - info.mMimeType); + continue; } } else { // yes it has mediaProviderUri column already filled in. - // delete it from MediaProvider database and then from downloads table - // in DownProvider database (the order of deletion is important). + // delete it from MediaProvider database. getContentResolver().delete(Uri.parse(info.mMediaProviderUri), null, null); - getContentResolver().delete(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, - Downloads.Impl._ID + " = ? ", - new String[]{String.valueOf(info.mId)}); } + // delete the file + deleteFileIfExists(info.mFileName); + // delete from the downloads db + getContentResolver().delete(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, + Downloads.Impl._ID + " = ? ", + new String[]{String.valueOf(info.mId)}); } } } @@ -463,29 +467,41 @@ public class DownloadService extends Service { * Drops old rows from the database to prevent it from growing too large */ private void trimDatabase() { - Cursor cursor = getContentResolver().query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, - new String[] { Downloads.Impl._ID }, - Downloads.Impl.COLUMN_STATUS + " >= '200'", null, - Downloads.Impl.COLUMN_LAST_MODIFICATION); - if (cursor == null) { - // This isn't good - if we can't do basic queries in our database, nothing's gonna work - Log.e(Constants.TAG, "null cursor in trimDatabase"); - return; - } - if (cursor.moveToFirst()) { - int numDelete = cursor.getCount() - Constants.MAX_DOWNLOADS; - int columnId = cursor.getColumnIndexOrThrow(Downloads.Impl._ID); - while (numDelete > 0) { - Uri downloadUri = ContentUris.withAppendedId( - Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, cursor.getLong(columnId)); - getContentResolver().delete(downloadUri, null, null); - if (!cursor.moveToNext()) { - break; + Cursor cursor = null; + try { + cursor = getContentResolver().query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, + new String[] { Downloads.Impl._ID }, + Downloads.Impl.COLUMN_STATUS + " >= '200'", null, + Downloads.Impl.COLUMN_LAST_MODIFICATION); + if (cursor == null) { + // This isn't good - if we can't do basic queries in our database, nothing's gonna work + Log.e(Constants.TAG, "null cursor in trimDatabase"); + return; + } + if (cursor.moveToFirst()) { + int numDelete = cursor.getCount() - Constants.MAX_DOWNLOADS; + int columnId = cursor.getColumnIndexOrThrow(Downloads.Impl._ID); + while (numDelete > 0) { + Uri downloadUri = ContentUris.withAppendedId( + Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, cursor.getLong(columnId)); + getContentResolver().delete(downloadUri, null, null); + if (!cursor.moveToNext()) { + break; + } + numDelete--; } - numDelete--; + } + } catch (SQLiteException e) { + // trimming the database raised an exception. alright, ignore the exception + // and return silently. trimming database is not exactly a critical operation + // and there is no need to propagate the exception. + Log.w(Constants.TAG, "trimDatabase failed with exception: " + e.getMessage()); + return; + } finally { + if (cursor != null) { + cursor.close(); } } - cursor.close(); } /** @@ -580,22 +596,28 @@ public class DownloadService extends Service { mMediaScannerService.requestScanFile(info.mFileName, info.mMimeType, new IMediaScannerListener.Stub() { public void scanCompleted(String path, Uri uri) { - if (uri != null && updateDatabase) { - // file is scanned and mediaprovider returned uri. store it in downloads - // table (i.e., update this downloaded file's row) + if (updateDatabase) { + // Mark this as 'scanned' in the database + // so that it is NOT subject to re-scanning by MediaScanner + // next time this database row row is encountered ContentValues values = new ContentValues(); values.put(Constants.MEDIA_SCANNED, 1); - values.put(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI, - uri.toString()); + if (uri != null) { + values.put(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI, + uri.toString()); + } getContentResolver().update(key, values, null, null); - } else if (uri == null && deleteFile) { - // callback returned NO uri..that means this file doesn't - // exist in MediaProvider. but it still needs to be deleted - // TODO don't scan files that are not scannable by MediaScanner. - // create a public method in MediaFile.java to return false - // if the given file's mimetype is not any of the types - // the mediaprovider is interested in. - Helpers.deleteFile(resolver, id, path, mimeType); + } else if (deleteFile) { + if (uri != null) { + // use the Uri returned to delete it from the MediaProvider + getContentResolver().delete(uri, null, null); + } + // delete the file and delete its row from the downloads db + deleteFileIfExists(path); + getContentResolver().delete( + Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, + Downloads.Impl._ID + " = ? ", + new String[]{String.valueOf(id)}); } } }); @@ -606,4 +628,15 @@ public class DownloadService extends Service { } } } + + private void deleteFileIfExists(String path) { + try { + if (!TextUtils.isEmpty(path)) { + File file = new File(path); + file.delete(); + } + } catch (Exception e) { + Log.w(Constants.TAG, "file: '" + path + "' couldn't be deleted", e); + } + } } |