summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Songchun Fan <schfan@google.com> 2023-08-15 16:53:32 -0700
committer Song Chun Fan <schfan@google.com> 2023-08-25 18:28:37 +0000
commitcc0de51a7d14d10e6d13e0c234b25e301bcbbdd2 (patch)
tree8f55f7ed8831d8992ac27fcbe20488fd78ef136f
parent242674523021aaea13f5cb87a496ebb03dff8c69 (diff)
[SettingsProvider] update ringtone cache only after setting is update
Previously RingtoneManager may override the ringtone cache even when the ringtone setting is not updated. This CL moves the cache update logic to SettingsProvider, and only updates the cache if the setting itself has been updated. BUG: 280219393 Test: manual with work profile creation Change-Id: I63ce56ef0cbfb8862ffbb56d7137a0f0223110a2
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--media/java/android/media/RingtoneManager.java35
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java124
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) {