Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad2c7ac0 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

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
parent bc2ae008
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -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
                    }
+0 −109
Original line number Diff line number Diff line
@@ -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