From ad2c7ac0871b25dbab99c973354c4270949d6280 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 26 Oct 2018 14:02:45 -0600 Subject: [PATCH] Move away from deprecated "_data" column. As part of the new privacy work in Q, apps no longer have access to raw filesystem paths, since they may live outside of the current sandbox. Instead, we need to use CR.openFileDescriptor(). Bug: 111960973 Test: builds, boots Change-Id: I6e52a7dcb39850d9835183c44f5f638a5bf77202 --- media/java/android/media/Ringtone.java | 6 +- media/java/android/media/RingtoneManager.java | 109 ------------------ 2 files changed, 2 insertions(+), 113 deletions(-) diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java index 32aba7fbd4826..84dfcb13083fe 100644 --- a/media/java/android/media/Ringtone.java +++ b/media/java/android/media/Ringtone.java @@ -23,13 +23,12 @@ import android.content.Context; import android.content.res.AssetFileDescriptor; import android.content.res.Resources.NotFoundException; import android.database.Cursor; -import android.media.MediaPlayer.OnCompletionListener; import android.net.Uri; import android.os.Binder; import android.os.RemoteException; import android.provider.MediaStore; -import android.provider.Settings; import android.provider.MediaStore.MediaColumns; +import android.provider.Settings; import android.util.Log; import java.io.IOException; @@ -50,7 +49,6 @@ public class Ringtone { private static final String[] MEDIA_COLUMNS = new String[] { MediaStore.Audio.Media._ID, - MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.TITLE }; /** Selection that limits query results to just audio files */ @@ -254,7 +252,7 @@ public class Ringtone { cursor = res.query(uri, MEDIA_COLUMNS, mediaSelection, null, null); if (cursor != null && cursor.getCount() == 1) { cursor.moveToFirst(); - return cursor.getString(2); + return cursor.getString(1); } // missing cursor is handled below } diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 8664aa12343be..436897fbf8b0a 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -497,34 +497,6 @@ public class RingtoneManager { return getUriFromCursor(mCursor); } - /** - * Queries the database for the Uri to a ringtone in a specific path (the ringtone has to have - * been scanned before) - * - * @param context Context used to query the database - * @param path Path to the ringtone file - * @return Uri of the ringtone, null if something fails in the query or the ringtone doesn't - * exist - * - * @hide - */ - private static Uri getExistingRingtoneUriFromPath(Context context, String path) { - final String[] proj = {MediaStore.Audio.Media._ID}; - final String[] selectionArgs = {path}; - try (final Cursor cursor = context.getContentResolver().query( - MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj, - MediaStore.Audio.Media.DATA + "=? ", selectionArgs, /* sortOrder */ null)) { - if (cursor == null || !cursor.moveToFirst()) { - return null; - } - final int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID)); - if (id == -1) { - return null; - } - return Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, "" + id); - } - } - private static Uri getUriFromCursor(Cursor cursor) { return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor .getLong(ID_COLUMN_INDEX)); @@ -749,28 +721,6 @@ public class RingtoneManager { return null; } - /** - * Look up the path for a given {@link Uri} referring to a ringtone sound (TYPE_RINGTONE, - * TYPE_NOTIFICATION, or TYPE_ALARM). This is saved in {@link MediaStore.Audio.Media#DATA}. - * - * @return a {@link File} pointing at the location of the {@param uri} on disk, or {@code null} - * if there is no such file. - */ - private File getRingtonePathFromUri(Uri uri) { - // Query cursor to get ringtone path - final String[] projection = {MediaStore.Audio.Media.DATA}; - setFilterColumnsList(TYPE_RINGTONE | TYPE_NOTIFICATION | TYPE_ALARM); - - String path = null; - try (Cursor cursor = query(uri, projection, constructBooleanTrueWhereClause(mFilterColumns), - null, null)) { - if (cursor != null && cursor.moveToFirst()) { - path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); - } - } - return path != null ? new File(path) : null; - } - /** * Disables Settings.System.SYNC_PARENT_SOUNDS. * @@ -879,32 +829,6 @@ public class RingtoneManager { : uriWithoutUserId.toString().startsWith(storage.toString()); } - /** @hide */ - public boolean isCustomRingtone(Uri uri) { - if(!isExternalRingtoneUri(uri)) { - // A custom ringtone would be in the external storage - return false; - } - - final File ringtoneFile = (uri == null ? null : getRingtonePathFromUri(uri)); - final File parent = (ringtoneFile == null ? null : ringtoneFile.getParentFile()); - if (parent == null) { - return false; - } - - final String[] directories = { - Environment.DIRECTORY_RINGTONES, - Environment.DIRECTORY_NOTIFICATIONS, - Environment.DIRECTORY_ALARMS - }; - for (final String directory : directories) { - if (parent.equals(Environment.getExternalStoragePublicDirectory(directory))) { - return true; - } - } - return false; - } - /** * Adds an audio file to the list of ringtones. * @@ -988,39 +912,6 @@ public class RingtoneManager { } } - /** - * Deletes the actual file in the Uri and its ringtone database entry if the Uri's actual path - * is in one of the following directories: {@link android.is.Environment#DIRECTORY_RINGTONES}, - * {@link android.is.Environment#DIRECTORY_NOTIFICATIONS} or - * {@link android.is.Environment#DIRECTORY_ALARMS}. - * - * The given Uri must be a ringtone Content Uri. - * - * Keep in mind that if the ringtone deleted is a default ringtone, it will still live in the - * ringtone cache file so it will be playable from there. However, if an app uses the ringtone - * as its own ringtone, it won't be played, which is the same behavior observed for 3rd party - * custom ringtones. - * - * @hide - */ - public boolean deleteExternalRingtone(Uri uri) { - if(!isCustomRingtone(uri)) { - // We can only delete custom ringtones in the default ringtone storages - return false; - } - - // Save the path of the ringtone before deleting from our content resolver. - final File ringtoneFile = getRingtonePathFromUri(uri); - try { - if (ringtoneFile != null && mContext.getContentResolver().delete(uri, null, null) > 0) { - return ringtoneFile.delete(); - } - } catch (SecurityException e) { - Log.d(TAG, "Unable to delete custom ringtone", e); - } - return false; - } - /** * Try opening the given ringtone locally first, but failover to * {@link IRingtonePlayer} if we can't access it directly. Typically happens