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

Commit 9683ffcf authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "[SettingsProvider] update ringtone cache only after setting is update"...

Merge "[SettingsProvider] update ringtone cache only after setting is update" into udc-qpr-dev am: 30ecbce9

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24605363



Change-Id: I55d00e9264f8e52a0589f13fe3b1aa55ccefbd55
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 4bf4e984 30ecbce9
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -5164,7 +5164,6 @@ public final class Settings {
        public static final Uri DEFAULT_RINGTONE_URI = getUriFor(RINGTONE);
        /** {@hide} */
        @Readable
        public static final String RINGTONE_CACHE = "ringtone_cache";
        /** {@hide} */
        public static final Uri RINGTONE_CACHE_URI = getUriFor(RINGTONE_CACHE);
+0 −35
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -934,18 +933,6 @@ public class RingtoneManager {

        Settings.System.putStringForUser(resolver, setting,
                ringtoneUri != null ? ringtoneUri.toString() : null, context.getUserId());

        // Stream selected ringtone into cache so it's available for playback
        // when CE storage is still locked
        if (ringtoneUri != null) {
            final Uri cacheUri = getCacheForType(type, context.getUserId());
            try (InputStream in = openRingtone(context, ringtoneUri);
                    OutputStream out = resolver.openOutputStream(cacheUri, "wt")) {
                FileUtils.copy(in, out);
            } catch (IOException e) {
                Log.w(TAG, "Failed to cache ringtone: " + e);
            }
        }
    }

    private static boolean isInternalRingtoneUri(Uri uri) {
@@ -1041,28 +1028,6 @@ public class RingtoneManager {
        }
    }

    /**
     * Try opening the given ringtone locally first, but failover to
     * {@link IRingtonePlayer} if we can't access it directly. Typically happens
     * when process doesn't hold
     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
     */
    private static InputStream openRingtone(Context context, Uri uri) throws IOException {
        final ContentResolver resolver = context.getContentResolver();
        try {
            return resolver.openInputStream(uri);
        } catch (SecurityException | IOException e) {
            Log.w(TAG, "Failed to open directly; attempting failover: " + e);
            final IRingtonePlayer player = context.getSystemService(AudioManager.class)
                    .getRingtonePlayer();
            try {
                return new ParcelFileDescriptor.AutoCloseInputStream(player.openRingtone(uri));
            } catch (Exception e2) {
                throw new IOException(e2);
            }
        }
    }

    private static String getSettingForType(int type) {
        if ((type & TYPE_RINGTONE) != 0) {
            return Settings.System.RINGTONE;
+94 −27
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import android.compat.annotation.EnabledSince;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -76,6 +77,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.hardware.camera2.utils.ArrayUtils;
import android.media.AudioManager;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -110,6 +112,7 @@ import android.provider.settings.validators.Validator;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -129,7 +132,10 @@ import libcore.util.HexEncoding;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
@@ -841,29 +847,68 @@ public class SettingsProvider extends ContentProvider {
        uri = ContentProvider.getUriWithoutUserId(uri);

        final String cacheRingtoneSetting;
        final String cacheName;
        if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) {
            cacheRingtoneSetting = Settings.System.RINGTONE;
            cacheName = Settings.System.RINGTONE_CACHE;
        } else if (Settings.System.NOTIFICATION_SOUND_CACHE_URI.equals(uri)) {
            cacheRingtoneSetting = Settings.System.NOTIFICATION_SOUND;
            cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
        } else if (Settings.System.ALARM_ALERT_CACHE_URI.equals(uri)) {
            cacheRingtoneSetting = Settings.System.ALARM_ALERT;
            cacheName = Settings.System.ALARM_ALERT_CACHE;
        } else {
            throw new FileNotFoundException("Direct file access no longer supported; "
                    + "ringtone playback is available through android.media.Ringtone");
        }

        final File cacheFile = getCacheFile(cacheRingtoneSetting, userId);
        return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode));
    }

    @Nullable
    private String getCacheName(String setting) {
        if (Settings.System.RINGTONE.equals(setting)) {
            return Settings.System.RINGTONE_CACHE;
        } else if (Settings.System.NOTIFICATION_SOUND.equals(setting)) {
            return Settings.System.NOTIFICATION_SOUND_CACHE;
        } else if (Settings.System.ALARM_ALERT.equals(setting)) {
            return Settings.System.ALARM_ALERT_CACHE;
        }
        return null;
    }

    @Nullable
    private File getCacheFile(String setting, int userId) {
        int actualCacheOwner;
        // Redirect cache to parent if ringtone setting is owned by profile parent
        synchronized (mLock) {
            actualCacheOwner = resolveOwningUserIdForSystemSettingLocked(userId,
                    cacheRingtoneSetting);
            actualCacheOwner = resolveOwningUserIdForSystemSettingLocked(userId, setting);
        }
        final String cacheName = getCacheName(setting);
        if (cacheName == null) {
            return null;
        }
        final File cacheFile = new File(getRingtoneCacheDir(actualCacheOwner), cacheName);
        return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode));
        return cacheFile;
    }


    /**
     * Try opening the given ringtone locally first, but failover to
     * {@link IRingtonePlayer} if we can't access it directly. Typically, happens
     * when process doesn't hold {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
     */
    private static InputStream openRingtone(Context context, Uri uri) throws IOException {
        final ContentResolver resolver = context.getContentResolver();
        try {
            return resolver.openInputStream(uri);
        } catch (SecurityException | IOException e) {
            Log.w(LOG_TAG, "Failed to open directly; attempting failover: " + e);
            final IRingtonePlayer player = context.getSystemService(AudioManager.class)
                    .getRingtonePlayer();
            try {
                return new ParcelFileDescriptor.AutoCloseInputStream(player.openRingtone(uri));
            } catch (Exception e2) {
                throw new IOException(e2);
            }
        }
    }

    private File getRingtoneCacheDir(int userId) {
@@ -1940,49 +1985,65 @@ public class SettingsProvider extends ContentProvider {
            return false;
        }

        // Invalidate any relevant cache files
        String cacheName = null;
        if (Settings.System.RINGTONE.equals(name)) {
            cacheName = Settings.System.RINGTONE_CACHE;
        } else if (Settings.System.NOTIFICATION_SOUND.equals(name)) {
            cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
        } else if (Settings.System.ALARM_ALERT.equals(name)) {
            cacheName = Settings.System.ALARM_ALERT_CACHE;
        }
        if (cacheName != null) {
        File cacheFile = getCacheFile(name, callingUserId);
        if (cacheFile != null) {
            if (!isValidAudioUri(name, value)) {
                return false;
            }
            final File cacheFile = new File(
                    getRingtoneCacheDir(owningUserId), cacheName);
            // Invalidate any relevant cache files
            cacheFile.delete();
        }

        final boolean success;
        // Mutate the value.
        synchronized (mLock) {
            switch (operation) {
                case MUTATION_OPERATION_INSERT: {
                    validateSystemSettingValue(name, value);
                    return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM,
                    success = mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM,
                            owningUserId, name, value, null, false, callingPackage,
                            false, null, overrideableByRestore);
                    break;
                }

                case MUTATION_OPERATION_DELETE: {
                    return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM,
                    success = mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM,
                            owningUserId, name, false, null);
                    break;
                }

                case MUTATION_OPERATION_UPDATE: {
                    validateSystemSettingValue(name, value);
                    return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM,
                    success = mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM,
                            owningUserId, name, value, null, false, callingPackage,
                            false, null);
                    break;
                }
            }

                default: {
                    success = false;
                    Slog.e(LOG_TAG, "Unknown operation code: " + operation);
                }
            }
        }

        if (!success) {
            return false;
        }

        if ((operation == MUTATION_OPERATION_INSERT || operation == MUTATION_OPERATION_UPDATE)
                && cacheFile != null && value != null) {
            final Uri ringtoneUri = Uri.parse(value);
            // Stream selected ringtone into cache, so it's available for playback
            // when CE storage is still locked
            try (InputStream in = openRingtone(getContext(), ringtoneUri);
                 OutputStream out = new FileOutputStream(cacheFile)) {
                FileUtils.copy(in, out);
            } catch (IOException e) {
                Slog.w(LOG_TAG, "Failed to cache ringtone: " + e);
            }
        }
        return true;
    }

    private boolean isValidAudioUri(String name, String uri) {
@@ -3269,20 +3330,21 @@ public class SettingsProvider extends ContentProvider {
            return Global.SECURE_FRP_MODE.equals(setting.getName());
        }

        public void resetSettingsLocked(int type, int userId, String packageName, int mode,
        public boolean resetSettingsLocked(int type, int userId, String packageName, int mode,
                String tag) {
            resetSettingsLocked(type, userId, packageName, mode, tag, /*prefix=*/
            return resetSettingsLocked(type, userId, packageName, mode, tag, /*prefix=*/
                    null);
        }

        public void resetSettingsLocked(int type, int userId, String packageName, int mode,
        public boolean resetSettingsLocked(int type, int userId, String packageName, int mode,
                String tag, @Nullable String prefix) {
            final int key = makeKey(type, userId);
            SettingsState settingsState = peekSettingsStateLocked(key);
            if (settingsState == null) {
                return;
                return false;
            }

            boolean success = false;
            banConfigurationIfNecessary(type, prefix, settingsState);
            switch (mode) {
                case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
@@ -3302,6 +3364,7 @@ public class SettingsProvider extends ContentProvider {
                        }
                        if (someSettingChanged) {
                            settingsState.persistSyncLocked();
                            success = true;
                        }
                    }
                } break;
@@ -3323,6 +3386,7 @@ public class SettingsProvider extends ContentProvider {
                        }
                        if (someSettingChanged) {
                            settingsState.persistSyncLocked();
                            success = true;
                        }
                    }
                } break;
@@ -3350,6 +3414,7 @@ public class SettingsProvider extends ContentProvider {
                        }
                        if (someSettingChanged) {
                            settingsState.persistSyncLocked();
                            success = true;
                        }
                    }
                } break;
@@ -3374,10 +3439,12 @@ public class SettingsProvider extends ContentProvider {
                        }
                        if (someSettingChanged) {
                            settingsState.persistSyncLocked();
                            success = true;
                        }
                    }
                } break;
            }
            return success;
        }

        public void removeSettingsForPackageLocked(String packageName, int userId) {