Merge "[SettingsProvider] update ringtone cache only after setting is update" into main
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b9a6583..45b4935 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5311,7 +5311,6 @@
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 9234479..c4f2159 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -38,7 +38,6 @@
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 @@
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 @@
}
}
- /**
- * 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 1cde26b..c0d1671 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.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.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.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 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 @@
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 @@
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 @@
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 @@
}
if (someSettingChanged) {
settingsState.persistSyncLocked();
+ success = true;
}
}
} break;
@@ -3343,6 +3405,7 @@
}
if (someSettingChanged) {
settingsState.persistSyncLocked();
+ success = true;
}
}
} break;
@@ -3370,6 +3433,7 @@
}
if (someSettingChanged) {
settingsState.persistSyncLocked();
+ success = true;
}
}
} break;
@@ -3394,10 +3458,12 @@
}
if (someSettingChanged) {
settingsState.persistSyncLocked();
+ success = true;
}
}
} break;
}
+ return success;
}
public void removeSettingsForPackageLocked(String packageName, int userId) {