Backup & restore for ringtone vibrations(2nd try)

This CL was reverted due to an autoRotation test
failure(b/372382424), fix the tests order as name
ascending to avoid it.

After CL[1] and CL[2], the ringtone/notification
support custome vibration playback.

If the user choose ringtone/notification with a
vibration, backup original value and use the same
value directly for restoring.

[1]: I8fc4f49e3801caec1dc2b0b611dd5b3854c6395f
[2]: I864c42b5c30f41328633bd37fe8fb571fb9cdbe4

Flag: android.media.audio.enable_ringtone_haptics_customization
Bug: 358525300
Bug: 371474327
Bug: 371471679
Bug: 372382424
Test: atest SettingsHelperTest
Test: Set up a ringtone with a vibration -> Backup the settings
-> Factory reset the device -> Restore the settings from the same
user -> Verify the ringtone and vibration are restored

Change-Id: Id3c1c1b52fb89e811cd016425e267a7a28e62930
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 1a99d25..65b2275 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -39,6 +39,7 @@
         "configinfra_framework_flags_java_lib",
         "device_config_service_flags_java",
         "libaconfig_java_proto_lite",
+        "notification_flags_lib",
         "SettingsLibDeviceStateRotationLock",
         "SettingsLibDisplayUtils",
     ],
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 6c31831..ebeee85 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -29,6 +29,7 @@
 import android.icu.util.ULocale;
 import android.media.AudioManager;
 import android.media.RingtoneManager;
+import android.media.Utils;
 import android.net.Uri;
 import android.os.LocaleList;
 import android.os.RemoteException;
@@ -309,6 +310,13 @@
                     return SILENT_RINGTONE;
                 }
             } else {
+                // If the ringtone/notification support the vibration, use the original value.
+                final int ringtoneType = getRingtoneType(name);
+                if ((ringtoneType == RingtoneManager.TYPE_RINGTONE
+                        || ringtoneType == RingtoneManager.TYPE_NOTIFICATION)
+                        && hasVibrationSettings(value, ringtoneType)) {
+                    return value;
+                }
                 return getCanonicalRingtoneValue(value);
             }
         }
@@ -362,6 +370,15 @@
             return;
         }
 
+        // If the ringtone/notification has vibration, we backup original value in onBackupValue.
+        // So use the value directly for restoring.
+        if ((ringtoneType == RingtoneManager.TYPE_RINGTONE
+                || ringtoneType == RingtoneManager.TYPE_NOTIFICATION)
+                && hasVibrationSettings(value, ringtoneType)) {
+            RingtoneManager.setActualDefaultRingtoneUri(mContext, ringtoneType, Uri.parse(value));
+            return;
+        }
+
         Uri ringtoneUri = null;
         try {
             ringtoneUri =
@@ -617,6 +634,19 @@
         return allLocales.remove(toFullLocale(filteredLocale));
     }
 
+    private boolean hasVibrationSettings(String value, int type) {
+        if (Utils.hasVibration(Uri.parse(value)) && mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported)) {
+            if (type == RingtoneManager.TYPE_RINGTONE) {
+                return android.media.audio.Flags.enableRingtoneHapticsCustomization();
+            }
+            if (type == RingtoneManager.TYPE_NOTIFICATION) {
+                return com.android.server.notification.Flags.notificationVibrationInSoundUri();
+            }
+        }
+        return false;
+    }
+
     /**
      * Sets the locale specified. Input data is the byte representation of comma separated
      * multiple BCP-47 language tags. For backwards compatibility, strings of the form
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
index 4b10b56..cea2bbc 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
@@ -37,9 +37,12 @@
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.media.AudioManager;
+import android.media.Utils;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.LocaleList;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.BaseColumns;
 import android.provider.MediaStore;
 import android.provider.Settings;
@@ -54,8 +57,11 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -63,6 +69,7 @@
  * Tests for the SettingsHelperTest
  */
 @RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class SettingsHelperTest {
     private static final String SETTING_KEY = "setting_key";
     private static final String SETTING_VALUE = "setting_value";
@@ -74,9 +81,13 @@
             "content://media/internal/audio/media/20?title=DefaultNotification&canonical=1";
     private static final String DEFAULT_ALARM_VALUE =
             "content://media/internal/audio/media/30?title=DefaultAlarm&canonical=1";
+    private static final String VIBRATION_FILE_NAME = "haptics.xml";
 
     private SettingsHelper mSettingsHelper;
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Mock private Context mContext;
     @Mock private Resources mResources;
     @Mock private AudioManager mAudioManager;
@@ -120,6 +131,22 @@
     }
 
     @Test
+    @EnableFlags({android.media.audio.Flags.FLAG_ENABLE_RINGTONE_HAPTICS_CUSTOMIZATION,
+            com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI})
+    public void testOnBackupValue_ringtoneVibrationSupport_returnsSameValue() {
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported)).thenReturn(
+                true);
+        String testRingtoneVibrationValue = createUriWithVibration(DEFAULT_RINGTONE_VALUE);
+        String testNotificationVibrationValue = createUriWithVibration(DEFAULT_NOTIFICATION_VALUE);
+
+        assertEquals(testRingtoneVibrationValue, mSettingsHelper.onBackupValue(
+                Settings.System.RINGTONE, testRingtoneVibrationValue));
+        assertEquals(testNotificationVibrationValue, mSettingsHelper.onBackupValue(
+                Settings.System.NOTIFICATION_SOUND, testNotificationVibrationValue));
+    }
+
+    @Test
     public void testGetRealValue_settingNotReplaced_returnsSameValue() {
         when(mSettingsHelper.isReplacedSystemSetting(eq(SETTING_KEY))).thenReturn(false);
 
@@ -675,6 +702,30 @@
                 .isEqualTo(null);
     }
 
+    @Test
+    @EnableFlags({android.media.audio.Flags.FLAG_ENABLE_RINGTONE_HAPTICS_CUSTOMIZATION,
+            com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI})
+    public void testRestoreValue_ringtoneVibrationSupport_restoreValue() {
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported)).thenReturn(
+                true);
+        String testRingtoneVibrationValue = createUriWithVibration(DEFAULT_RINGTONE_VALUE);
+        String testNotificationVibrationValue = createUriWithVibration(DEFAULT_NOTIFICATION_VALUE);
+        ContentProvider mockMediaContentProvider =
+                new MockContentProvider(mContext) {
+                    @Override
+                    public String getType(Uri url) {
+                        return "audio/ogg";
+                    }
+                };
+        mContentResolver.addProvider(MediaStore.AUTHORITY, mockMediaContentProvider);
+        resetRingtoneSettingsToDefault();
+
+        assertRingtoneSettingsRestoring(Settings.System.RINGTONE, testRingtoneVibrationValue);
+        assertRingtoneSettingsRestoring(
+                Settings.System.NOTIFICATION_SOUND, testNotificationVibrationValue);
+    }
+
     private static class MockSettingsProvider extends MockContentProvider {
         private final ArrayMap<String, String> mKeyValueStore = new ArrayMap<>();
         MockSettingsProvider(Context context) {
@@ -766,4 +817,25 @@
         assertThat(Settings.System.getString(mContentResolver, Settings.System.ALARM_ALERT))
                 .isEqualTo(DEFAULT_ALARM_VALUE);
     }
+
+    private String createUriWithVibration(String defaultUriString) {
+        return Uri.parse(defaultUriString).buildUpon()
+                .appendQueryParameter(
+                        Utils.VIBRATION_URI_PARAM, VIBRATION_FILE_NAME).build().toString();
+    }
+
+    private void assertRingtoneSettingsRestoring(
+            String settings, String testRingtoneSettingsValue) {
+        mSettingsHelper.restoreValue(
+                mContext,
+                mContentResolver,
+                new ContentValues(),
+                Uri.EMPTY,
+                settings,
+                testRingtoneSettingsValue,
+                0);
+
+        assertThat(Settings.System.getString(mContentResolver, settings))
+                .isEqualTo(testRingtoneSettingsValue);
+    }
 }