Scan after writing download files.
Jeff Sharkey [Tue, 5 Aug 2014 18:51:24 +0000 (11:51 -0700)]
Kicks off media scanner after files are written, usually through a
DocumentsProvider.

Bug: 13557203
Change-Id: I4e29b778b4e19a217f60c1e415c4d814724752d3

src/com/android/providers/downloads/Constants.java
src/com/android/providers/downloads/DownloadInfo.java
src/com/android/providers/downloads/DownloadProvider.java
src/com/android/providers/downloads/DownloadStorageProvider.java

index 2803d1c..7b8fcd2 100644 (file)
@@ -45,9 +45,6 @@ public class Constants {
     /** The column that is used for the initiating app's UID */
     public static final String UID = "uid";
 
-    /** The column that is used to remember whether the media scanner was invoked */
-    public static final String MEDIA_SCANNED = "scanned";
-
     /** The intent that gets sent when the service must wake up for a retry */
     public static final String ACTION_RETRY = "android.intent.action.DOWNLOAD_WAKEUP";
 
index 3571a78..2423c0d 100644 (file)
@@ -94,7 +94,7 @@ public class DownloadInfo {
             info.mCurrentBytes = getLong(Downloads.Impl.COLUMN_CURRENT_BYTES);
             info.mETag = getString(Constants.ETAG);
             info.mUid = getInt(Constants.UID);
-            info.mMediaScanned = getInt(Constants.MEDIA_SCANNED);
+            info.mMediaScanned = getInt(Downloads.Impl.COLUMN_MEDIA_SCANNED);
             info.mDeleted = getInt(Downloads.Impl.COLUMN_DELETED) == 1;
             info.mMediaProviderUri = getString(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI);
             info.mIsPublicApi = getInt(Downloads.Impl.COLUMN_IS_PUBLIC_API) != 0;
index 59e753e..5b45c3f 100644 (file)
@@ -414,7 +414,7 @@ public final class DownloadProvider extends ContentProvider {
                         Downloads.Impl.COLUMN_OTHER_UID + " INTEGER, " +
                         Downloads.Impl.COLUMN_TITLE + " TEXT, " +
                         Downloads.Impl.COLUMN_DESCRIPTION + " TEXT, " +
-                        Constants.MEDIA_SCANNED + " BOOLEAN);");
+                        Downloads.Impl.COLUMN_MEDIA_SCANNED + " BOOLEAN);");
             } catch (SQLException ex) {
                 Log.e(Constants.TAG, "couldn't create table in downloads database");
                 throw ex;
@@ -1182,8 +1182,12 @@ public final class DownloadProvider extends ContentProvider {
             logVerboseOpenFileInfo(uri, mode);
         }
 
-        final Cursor cursor = query(uri, new String[] { Downloads.Impl._DATA }, null, null, null);
-        String path;
+        final Cursor cursor = query(uri, new String[] {
+                Downloads.Impl._DATA, Downloads.Impl.COLUMN_STATUS,
+                Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.COLUMN_MEDIA_SCANNED }, null,
+                null, null);
+        final String path;
+        final boolean shouldScan;
         try {
             int count = (cursor != null) ? cursor.getCount() : 0;
             if (count != 1) {
@@ -1194,8 +1198,20 @@ public final class DownloadProvider extends ContentProvider {
                 throw new FileNotFoundException("Multiple items at " + uri);
             }
 
-            cursor.moveToFirst();
-            path = cursor.getString(0);
+            if (cursor.moveToFirst()) {
+                final int status = cursor.getInt(1);
+                final int destination = cursor.getInt(2);
+                final int mediaScanned = cursor.getInt(3);
+
+                path = cursor.getString(0);
+                shouldScan = Downloads.Impl.isStatusSuccess(status) && (
+                        destination == Downloads.Impl.DESTINATION_EXTERNAL
+                        || destination == Downloads.Impl.DESTINATION_FILE_URI
+                        || destination == Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD)
+                        && mediaScanned != 2;
+            } else {
+                throw new FileNotFoundException("Failed moveToFirst");
+            }
         } finally {
             IoUtils.closeQuietly(cursor);
         }
@@ -1209,22 +1225,29 @@ public final class DownloadProvider extends ContentProvider {
             throw new FileNotFoundException("Invalid file: " + file);
         }
 
-        if ("r".equals(mode)) {
-            return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+        final int pfdMode = ParcelFileDescriptor.parseMode(mode);
+        if (pfdMode == ParcelFileDescriptor.MODE_READ_ONLY) {
+            return ParcelFileDescriptor.open(file, pfdMode);
         } else {
             try {
                 // When finished writing, update size and timestamp
-                return ParcelFileDescriptor.open(file, ParcelFileDescriptor.parseMode(mode),
-                        mHandler, new OnCloseListener() {
-                            @Override
-                            public void onClose(IOException e) {
-                                final ContentValues values = new ContentValues();
-                                values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, file.length());
-                                values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION,
-                                        System.currentTimeMillis());
-                                update(uri, values, null, null);
-                            }
-                        });
+                return ParcelFileDescriptor.open(file, pfdMode, mHandler, new OnCloseListener() {
+                    @Override
+                    public void onClose(IOException e) {
+                        final ContentValues values = new ContentValues();
+                        values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, file.length());
+                        values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION,
+                                System.currentTimeMillis());
+                        update(uri, values, null, null);
+
+                        if (shouldScan) {
+                            final Intent intent = new Intent(
+                                    Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+                            intent.setData(Uri.fromFile(file));
+                            getContext().sendBroadcast(intent);
+                        }
+                    }
+                });
             } catch (IOException e) {
                 throw new FileNotFoundException("Failed to open for writing: " + e);
             }
index ecef54e..78b3c43 100644 (file)
@@ -133,7 +133,7 @@ public class DownloadStorageProvider extends DocumentsProvider {
             }
 
             return Long.toString(mDm.addCompletedDownload(
-                    file.getName(), file.getName(), false, mimeType, file.getAbsolutePath(), 0L,
+                    file.getName(), file.getName(), true, mimeType, file.getAbsolutePath(), 0L,
                     false, true));
         } finally {
             Binder.restoreCallingIdentity(token);