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();
+        }
+    }
 }