diff options
3 files changed, 95 insertions, 65 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b9a658344e7d..45b49359f46e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5311,7 +5311,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); diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 9234479ea8fd..c4f2159a23dc 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -38,7 +38,6 @@ import android.database.StaleDataException; import android.net.Uri; import android.os.Environment; import android.os.FileUtils; -import android.os.ParcelFileDescriptor; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -993,18 +992,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) { @@ -1100,28 +1087,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; diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 1cde26b00223..c0d16712b255 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -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; @@ -849,29 +855,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) { @@ -1953,55 +1998,70 @@ 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; } case MUTATION_OPERATION_RESET: { - mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_SYSTEM, + success = mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_SYSTEM, runAsUserId, callingPackage, mode, tag); - return true; + break; } + + default: + success = false; + Slog.e(LOG_TAG, "Unknown operation code: " + operation); } - 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) { @@ -3289,20 +3349,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: { @@ -3322,6 +3383,7 @@ public class SettingsProvider extends ContentProvider { } if (someSettingChanged) { settingsState.persistSyncLocked(); + success = true; } } } break; @@ -3343,6 +3405,7 @@ public class SettingsProvider extends ContentProvider { } if (someSettingChanged) { settingsState.persistSyncLocked(); + success = true; } } } break; @@ -3370,6 +3433,7 @@ public class SettingsProvider extends ContentProvider { } if (someSettingChanged) { settingsState.persistSyncLocked(); + success = true; } } } break; @@ -3394,10 +3458,12 @@ public class SettingsProvider extends ContentProvider { } if (someSettingChanged) { settingsState.persistSyncLocked(); + success = true; } } } break; } + return success; } public void removeSettingsForPackageLocked(String packageName, int userId) { |