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

Commit 452ffae8 authored by Wenhao Shi's avatar Wenhao Shi Committed by Cherrypicker Worker
Browse files

Implemement the media lookup for ringtone restore in SettingsProvider.

Bug: 278169915
Test: atest SettingsProviderTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a26e28d5d9f42540fcf58ad95206bf5068af4a9d)
Merged-In: Ib401f64e08a6297577672aea30a09b63f28dcf41
Change-Id: Ib401f64e08a6297577672aea30a09b63f28dcf41
parent bb87028a
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
@@ -46,7 +46,9 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.AudioColumns;
import android.provider.MediaStore.MediaColumns;
import android.provider.Settings;
import android.provider.Settings.System;
@@ -507,6 +509,95 @@ public class RingtoneManager {
        return getUriFromCursor(mContext, mCursor);
    }

    /**
     * Gets the valid ringtone uri by a given uri string and ringtone type for the restore purpose.
     *
     * @param contentResolver ContentResolver to execute media query.
     * @param value a canonicalized uri which refers to the ringtone.
     * @param ringtoneType an integer representation of the kind of uri that is being restored, can
     *     be RingtoneManager.TYPE_RINGTONE, RingtoneManager.TYPE_NOTIFICATION, or
     *     RingtoneManager.TYPE_ALARM.
     * @hide
     */
    public static @Nullable Uri getRingtoneUriForRestore(
            @NonNull ContentResolver contentResolver, @Nullable String value, int ringtoneType)
            throws FileNotFoundException, IllegalArgumentException {
        if (value == null) {
            // Return a valid null. It means the null value is intended instead of a failure.
            return null;
        }

        Uri ringtoneUri;
        final Uri canonicalUri = Uri.parse(value);

        // Try to get the media uri via the regular uncanonicalize method first.
        ringtoneUri = contentResolver.uncanonicalize(canonicalUri);
        if (ringtoneUri != null) {
            // Canonicalize it to make the result contain the right metadata of the media asset.
            ringtoneUri = contentResolver.canonicalize(ringtoneUri);
            return ringtoneUri;
        }

        // Query the media by title and ringtone type.
        final String title = canonicalUri.getQueryParameter(AudioColumns.TITLE);
        Uri baseUri = ContentUris.removeId(canonicalUri).buildUpon().clearQuery().build();
        String ringtoneTypeSelection = "";
        switch (ringtoneType) {
            case RingtoneManager.TYPE_RINGTONE:
                ringtoneTypeSelection = MediaStore.Audio.AudioColumns.IS_RINGTONE;
                break;
            case RingtoneManager.TYPE_NOTIFICATION:
                ringtoneTypeSelection = MediaStore.Audio.AudioColumns.IS_NOTIFICATION;
                break;
            case RingtoneManager.TYPE_ALARM:
                ringtoneTypeSelection = MediaStore.Audio.AudioColumns.IS_ALARM;
                break;
            default:
                throw new IllegalArgumentException("Unknown ringtone type: " + ringtoneType);
        }

        final String selection = ringtoneTypeSelection + "=1 AND " + AudioColumns.TITLE + "=?";
        Cursor cursor = null;
        try {
            cursor =
                    contentResolver.query(
                            baseUri,
                            /* projection */ new String[] {BaseColumns._ID},
                            /* selection */ selection,
                            /* selectionArgs */ new String[] {title},
                            /* sortOrder */ null,
                            /* cancellationSignal */ null);

        } catch (IllegalArgumentException e) {
            throw new FileNotFoundException("Volume not found for " + baseUri);
        }
        if (cursor == null) {
            throw new FileNotFoundException("Missing cursor for " + baseUri);
        } else if (cursor.getCount() == 0) {
            FileUtils.closeQuietly(cursor);
            throw new FileNotFoundException("No item found for " + baseUri);
        } else if (cursor.getCount() > 1) {
            // Find more than 1 result.
            // We are not sure which one is the right ringtone file so just abandon this case.
            FileUtils.closeQuietly(cursor);
            throw new FileNotFoundException(
                    "Find multiple ringtone candidates by title+ringtone_type query: count: "
                            + cursor.getCount());
        }
        if (cursor.moveToFirst()) {
            ringtoneUri = ContentUris.withAppendedId(baseUri, cursor.getLong(0));
            FileUtils.closeQuietly(cursor);
        } else {
            FileUtils.closeQuietly(cursor);
            throw new FileNotFoundException("Failed to read row from the result.");
        }

        // Canonicalize it to make the result contain the right metadata of the media asset.
        ringtoneUri = contentResolver.canonicalize(ringtoneUri);
        Log.v(TAG, "Find a valid result: " + ringtoneUri);
        return ringtoneUri;
    }

    private static Uri getUriFromCursor(Context context, Cursor cursor) {
        final Uri uri = ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)),
                cursor.getLong(ID_COLUMN_INDEX));
+21 −11
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.LocalePicker;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
@@ -332,21 +333,30 @@ public class SettingsHelper {
     * @param value can be a canonicalized uri or "_silent" to indicate a silent (null) ringtone.
     */
    private void setRingtone(String name, String value) {
        // If it's null, don't change the default
        Log.v(TAG, "Set ringtone for name: " + name + " value: " + value);

        // If it's null, don't change the default.
        if (value == null) return;
        final Uri ringtoneUri;
        final int ringtoneType = getRingtoneType(name);
        if (SILENT_RINGTONE.equals(value)) {
            ringtoneUri = null;
        } else {
            Uri canonicalUri = Uri.parse(value);
            ringtoneUri = mContext.getContentResolver().uncanonicalize(canonicalUri);
            if (ringtoneUri == null) {
                // Unrecognized or invalid Uri, don't restore
            // SILENT_RINGTONE is a special constant generated by onBackupValue in the source
            // device.
            RingtoneManager.setActualDefaultRingtoneUri(mContext, ringtoneType, null);
            return;
        }

        Uri ringtoneUri = null;
        try {
            ringtoneUri =
                    RingtoneManager.getRingtoneUriForRestore(
                            mContext.getContentResolver(), value, ringtoneType);
        } catch (FileNotFoundException | IllegalArgumentException e) {
            Log.w(TAG, "Failed to resolve " + value + ": " + e);
            // Unrecognized or invalid Uri, don't restore
            return;
        }
        final int ringtoneType = getRingtoneType(name);

        Log.v(TAG, "setActualDefaultRingtoneUri type: " + ringtoneType + ", uri: " + ringtoneUri);
        RingtoneManager.setActualDefaultRingtoneUri(mContext, ringtoneType, ringtoneUri);
    }

+404 −0

File changed.

Preview size limit exceeded, changes collapsed.