summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/providers/downloads/DownloadProvider.java145
1 files changed, 132 insertions, 13 deletions
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java
index 8dc14506..d4468da3 100644
--- a/src/com/android/providers/downloads/DownloadProvider.java
+++ b/src/com/android/providers/downloads/DownloadProvider.java
@@ -62,7 +62,10 @@ import android.provider.MediaStore.Files;
import android.provider.OpenableColumns;
import android.text.TextUtils;
import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.util.Log;
+import android.util.LongArray;
+import android.util.LongSparseArray;
import com.android.internal.util.IndentingPrintWriter;
@@ -378,12 +381,13 @@ public final class DownloadProvider extends ContentProvider {
final DownloadInfo.Reader reader
= new DownloadInfo.Reader(getContext().getContentResolver(), cursor);
final DownloadInfo info = new DownloadInfo(getContext());
+ final ContentValues updateValues = new ContentValues();
while (cursor.moveToNext()) {
reader.updateFromDatabase(info);
final Uri mediaStoreUri = updateMediaProvider(client, null,
convertToMediaProviderValues(info));
if (mediaStoreUri != null) {
- final ContentValues updateValues = new ContentValues();
+ updateValues.clear();
updateValues.put(Downloads.Impl.COLUMN_MEDIASTORE_URI,
mediaStoreUri.toString());
db.update(DB_TABLE, updateValues, Downloads.Impl._ID + "=?",
@@ -806,6 +810,7 @@ public final class DownloadProvider extends ContentProvider {
return isVisibleInDownloads ? mediaStoreUri : null;
}
} catch (RemoteException e) {
+ // Should not happen
}
return null;
}
@@ -826,6 +831,7 @@ public final class DownloadProvider extends ContentProvider {
return ContentUris.withAppendedId(filesUri, cursor.getLong(0));
}
} catch (RemoteException e) {
+ // Should not happen
}
return null;
}
@@ -1138,13 +1144,100 @@ public final class DownloadProvider extends ContentProvider {
final SQLiteQueryBuilder qb = getQueryBuilder(uri, match);
+ // map of volumeName -> { mediastore ids that need to be queried }
+ final ArrayMap<String, LongArray> mediaStoreIdsForVolumes = new ArrayMap<>();
+ try (Cursor cursor = qb.query(db, new String[] { Downloads.Impl.COLUMN_MEDIASTORE_URI },
+ selection, selectionArgs, null, null, sort)) {
+ while (cursor.moveToNext()) {
+ final String uriString = cursor.getString(0);
+ if (uriString == null) {
+ continue;
+ }
+ final Uri mediaStoreUri = Uri.parse(uriString);
+ final String volumeName = MediaStore.getVolumeName(mediaStoreUri);
+ LongArray ids = mediaStoreIdsForVolumes.get(volumeName);
+ if (ids == null) {
+ ids = new LongArray();
+ mediaStoreIdsForVolumes.put(volumeName, ids);
+ }
+ ids.add(ContentUris.parseId(mediaStoreUri));
+ }
+ }
+ // map of volumeName -> { map of {mediastore id -> mediastore data} }
+ final ArrayMap<String, LongSparseArray<MediaStoreData>> mediaStoreDataForVolumes
+ = new ArrayMap<>();
+ final CallingIdentity token = clearCallingIdentity();
+ try (ContentProviderClient client = getContext().getContentResolver()
+ .acquireContentProviderClient(MediaStore.AUTHORITY)) {
+ final String[] projectionIn = new String[] {
+ MediaStore.Downloads._ID,
+ MediaStore.Downloads.DISPLAY_NAME,
+ MediaStore.Downloads.DATA,
+ };
+ for (int i = 0; i < mediaStoreIdsForVolumes.size(); ++i) {
+ final String volumeName = mediaStoreIdsForVolumes.keyAt(i);
+ final LongArray ids = mediaStoreIdsForVolumes.valueAt(i);
+ final LongSparseArray<MediaStoreData> mediaStoreDataForIds
+ = new LongSparseArray<>();
+ mediaStoreDataForVolumes.put(volumeName, mediaStoreDataForIds);
+ try (Cursor mediaCursor = getMediaProviderRowsForIds(
+ client, projectionIn, volumeName, ids)) {
+ while (mediaCursor.moveToNext()) {
+ final long id = mediaCursor.getLong(0);
+ final String displayName = mediaCursor.getString(1);
+ final String filePath = mediaCursor.getString(2);
+ mediaStoreDataForIds.put(id, new MediaStoreData(displayName, filePath));
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ // Should not happen
+ } finally {
+ restoreCallingIdentity(token);
+ }
+
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final TranslatingCursor.Config config = getTranslatingCursorConfig(match);
final TranslatingCursor.Translator translator
- = (data, id) -> translateSystemToApp(data, pid, uid);
- final Cursor ret = TranslatingCursor.query(config, translator, qb, db,
- projection, selection, selectionArgs, null, null, sort, null, null);
+ = (data, auxiliaryColIndex, matchingColumn, cursor) -> {
+ final String uriString = cursor.getString(auxiliaryColIndex);
+ if (uriString != null) {
+ final Uri mediaStoreUri = Uri.parse(uriString);
+ final String volumeName = MediaStore.getVolumeName(mediaStoreUri);
+ final LongSparseArray<MediaStoreData> mediaStoreDataForIds
+ = mediaStoreDataForVolumes.get(volumeName);
+ if (mediaStoreDataForIds != null) {
+ final long id = ContentUris.parseId(mediaStoreUri);
+ final MediaStoreData mediaStoreData = mediaStoreDataForIds.get(id);
+ if (mediaStoreData != null) {
+ switch (matchingColumn) {
+ case Downloads.Impl.COLUMN_TITLE:
+ data = mediaStoreData.displayName;
+ break;
+ case Downloads.Impl._DATA:
+ case Downloads.Impl.COLUMN_FILE_NAME_HINT:
+ case DownloadManager.COLUMN_LOCAL_FILENAME:
+ data = mediaStoreData.filePath;
+ break;
+ default:
+ return data;
+ }
+ }
+ }
+ }
+
+ switch (matchingColumn) {
+ case Downloads.Impl._DATA:
+ case Downloads.Impl.COLUMN_FILE_NAME_HINT:
+ case DownloadManager.COLUMN_LOCAL_FILENAME:
+ return translateSystemToApp(data, pid, uid);
+ default:
+ return data;
+ }
+ };
+ final Cursor ret = TranslatingCursor.query(config, translator,
+ qb, db, projection, selection, selectionArgs, null, null, sort, null, null);
if (ret != null) {
ret.setNotificationUri(getContext().getContentResolver(), uri);
@@ -1161,6 +1254,19 @@ public final class DownloadProvider extends ContentProvider {
return ret;
}
+ private Cursor getMediaProviderRowsForIds(ContentProviderClient mediaProvider,
+ String[] projection, String volumeName, LongArray ids) throws RemoteException {
+ final StringBuilder queryString = new StringBuilder();
+ queryString.append(MediaStore.Downloads._ID + " in (");
+ final int size = ids.size();
+ for (int i = 0; i < size; ++i) {
+ queryString.append(ids.get(i));
+ queryString.append((i == size - 1) ? ")" : ",");
+ }
+ return mediaProvider.query(MediaStore.Downloads.getContentUri(volumeName),
+ projection, queryString.toString(), null, null);
+ }
+
private TranslatingCursor.Config getTranslatingCursorConfig(int match) {
final Uri baseUri;
switch (match) {
@@ -1175,9 +1281,11 @@ public final class DownloadProvider extends ContentProvider {
default:
baseUri = null;
}
- return new TranslatingCursor.Config(baseUri,
- Downloads.Impl._ID, Downloads.Impl._DATA, Downloads.Impl.COLUMN_FILE_NAME_HINT,
- DownloadManager.COLUMN_LOCAL_FILENAME);
+ return new TranslatingCursor.Config(baseUri, Downloads.Impl.COLUMN_MEDIASTORE_URI,
+ Downloads.Impl._DATA,
+ Downloads.Impl.COLUMN_FILE_NAME_HINT,
+ DownloadManager.COLUMN_LOCAL_FILENAME,
+ Downloads.Impl.COLUMN_TITLE);
}
private void logVerboseQueryInfo(String[] projection, final String selection,
@@ -1345,16 +1453,17 @@ public final class DownloadProvider extends ContentProvider {
final DownloadInfo.Reader reader = new DownloadInfo.Reader(resolver,
cursor);
final DownloadInfo info = new DownloadInfo(context);
+ final ContentValues updateValues = new ContentValues();
while (cursor.moveToNext()) {
reader.updateFromDatabase(info);
if (info.mFileName == null) {
if (info.mMediaStoreUri != null) {
client.delete(Uri.parse(info.mMediaStoreUri), null, null);
+ updateValues.clear();
+ updateValues.putNull(Downloads.Impl.COLUMN_MEDIASTORE_URI);
+ qb.update(db, updateValues, Downloads.Impl._ID + "=?",
+ new String[] { Long.toString(info.mId) });
}
- final ContentValues updateValues = new ContentValues();
- updateValues.putNull(Downloads.Impl.COLUMN_MEDIASTORE_URI);
- qb.update(db, updateValues, Downloads.Impl._ID + "=?",
- new String[] { Long.toString(info.mId) });
} else if (info.mDestination == Downloads.Impl.DESTINATION_EXTERNAL
|| info.mDestination == Downloads.Impl.DESTINATION_FILE_URI
|| info.mDestination == Downloads.Impl
@@ -1363,7 +1472,7 @@ public final class DownloadProvider extends ContentProvider {
info.mMediaStoreUri, convertToMediaProviderValues(info));
if (!TextUtils.equals(info.mMediaStoreUri,
mediaStoreUri == null ? null : mediaStoreUri.toString())) {
- final ContentValues updateValues = new ContentValues();
+ updateValues.clear();
if (mediaStoreUri == null) {
updateValues.putNull(Downloads.Impl.COLUMN_MEDIASTORE_URI);
} else {
@@ -1371,7 +1480,7 @@ public final class DownloadProvider extends ContentProvider {
mediaStoreUri.toString());
}
qb.update(db, updateValues, Downloads.Impl._ID + "=?",
- new String[]{Long.toString(info.mId)});
+ new String[] { Long.toString(info.mId) });
}
}
if (updateSchedule) {
@@ -1779,4 +1888,14 @@ public final class DownloadProvider extends ContentProvider {
final Uri uri = ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id);
getContext().revokeUriPermission(uri, ~0);
}
+
+ private static final class MediaStoreData {
+ public String displayName;
+ public String filePath;
+
+ public MediaStoreData(String displayName, String filePath) {
+ this.displayName = displayName;
+ this.filePath = filePath;
+ }
+ }
}