Move default ringtone configuration to framework.
This ensures that partners have a place to customize the default
ringtone configuration, such as adding support for per-SIM ringtones
which aren't officially supported by Android yet.
Bug: 141596983, 141518853, 141594113, 141595768, 141809410
Test: atest --test-mapping packages/providers/MediaProvider
Change-Id: Ibe5b41c09ca40caadfcbb81162b996173fe8509b
diff --git a/api/system-current.txt b/api/system-current.txt
index f5e7523..de96c19 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3648,6 +3648,10 @@
method public void stop();
}
+ public class RingtoneManager {
+ method @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void ensureDefaultRingtones(@NonNull android.content.Context);
+ }
+
}
package android.media.audiopolicy {
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index ff40442..9064e68 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -22,6 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.Activity;
@@ -40,9 +41,11 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.MediaStore;
+import android.provider.MediaStore.MediaColumns;
import android.provider.Settings;
import android.provider.Settings.System;
import android.util.Log;
@@ -1097,4 +1100,62 @@
return null;
}
}
+
+ /**
+ * Ensure that ringtones have been set at least once on this device. This
+ * should be called after the device has finished scanned all media on
+ * {@link MediaStore#VOLUME_INTERNAL}, so that default ringtones can be
+ * configured.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS)
+ public static void ensureDefaultRingtones(@NonNull Context context) {
+ for (int type : new int[] {
+ TYPE_RINGTONE,
+ TYPE_NOTIFICATION,
+ TYPE_ALARM,
+ }) {
+ // Skip if we've already defined it at least once, so we don't
+ // overwrite the user changing to null
+ final String setting = getDefaultRingtoneSetting(type);
+ if (Settings.System.getInt(context.getContentResolver(), setting, 0) != 0) {
+ continue;
+ }
+
+ // Try finding the scanned ringtone
+ final String filename = getDefaultRingtoneFilename(type);
+ final Uri baseUri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
+ try (Cursor cursor = context.getContentResolver().query(baseUri,
+ new String[] { MediaColumns._ID },
+ MediaColumns.DISPLAY_NAME + "=?",
+ new String[] { filename }, null)) {
+ if (cursor.moveToFirst()) {
+ final Uri ringtoneUri = context.getContentResolver().canonicalizeOrElse(
+ ContentUris.withAppendedId(baseUri, cursor.getLong(0)));
+ RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri);
+ Settings.System.putInt(context.getContentResolver(), setting, 1);
+ }
+ }
+ }
+ }
+
+ private static String getDefaultRingtoneSetting(int type) {
+ switch (type) {
+ case TYPE_RINGTONE: return "ringtone_set";
+ case TYPE_NOTIFICATION: return "notification_sound_set";
+ case TYPE_ALARM: return "alarm_alert_set";
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ private static String getDefaultRingtoneFilename(int type) {
+ switch (type) {
+ case TYPE_RINGTONE: return SystemProperties.get("ro.config.ringtone");
+ case TYPE_NOTIFICATION: return SystemProperties.get("ro.config.notification_sound");
+ case TYPE_ALARM: return SystemProperties.get("ro.config.alarm_alert");
+ default: throw new IllegalArgumentException();
+ }
+ }
}