Don't copy ringtones when profile sync goes off

Experimentally, it makes more sense to more people to have the parent
setting as an overlay not a concrete thing.

Test: make cts -j30 && cts-tradefed run cts --module CtsDevicePolicyManagerTestCases --test 'com.android.cts.devicepolicy.ManagedProfileTest#testRingtoneSyncAutoDisableRingtone' </dev/null 2>&1
Bug: 34730524
Change-Id: I5f804713def9e54921b90e4f5cea742ba8aaa685
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c9b1c9c..143b98c 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4635,7 +4635,7 @@
                 return setLocationModeForUser(resolver, Integer.parseInt(value), userHandle);
             }
             if (MOVED_TO_GLOBAL.contains(name)) {
-                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure"
                         + " to android.provider.Settings.Global");
                 return Global.putStringForUser(resolver, name, value,
                         tag, makeDefault, userHandle);
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index fa4796a..5855984 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -192,7 +192,7 @@
 
     oneway void releasePlayer(in int piid);
 
-    void disableRingtoneSync();
+    void disableRingtoneSync(in int userId);
 
     int getFocusRampTimeMs(in int focusGain, in AudioAttributes attr);
 
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 8a1027b..e774c71 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -103,10 +103,6 @@
      */
     public static final int TYPE_ALL = TYPE_RINGTONE | TYPE_NOTIFICATION | TYPE_ALARM;
 
-    private static final int[] RINGTONE_TYPES = {
-            TYPE_RINGTONE, TYPE_NOTIFICATION, TYPE_ALARM
-    };
-    
     // </attr>
     
     /**
@@ -773,30 +769,17 @@
     }
 
     /**
-     * Disables Settings.System.SYNC_PARENT_SOUNDS, copying the parent's ringtones to the current
-     * profile
+     * Disables Settings.System.SYNC_PARENT_SOUNDS.
      *
      * @hide
      */
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
     public static void disableSyncFromParent(Context userContext) {
-        // Must disable sync first so that ringtone copy below doesn't get redirected to parent
-        Settings.Secure.putIntForUser(userContext.getContentResolver(),
-                Settings.Secure.SYNC_PARENT_SOUNDS, 0 /* false */, userContext.getUserId());
-
-        // Copy ringtones from parent profile
-        UserManager um = UserManager.get(userContext);
-        UserInfo parentInfo = um.getProfileParent(userContext.getUserId());
-        if (parentInfo != null) {
-            final Context targetContext = createPackageContextAsUser(userContext, parentInfo.id);
-            if (targetContext != null) {
-                for (int ringtoneType : RINGTONE_TYPES) {
-                    Uri ringtoneUri = getActualDefaultRingtoneUri(targetContext, ringtoneType);
-                    // Add user id of parent so that custom ringtones can be read and played
-                    RingtoneManager.setActualDefaultRingtoneUri(userContext, ringtoneType,
-                            maybeAddUserId(ringtoneUri, parentInfo.id));
-                }
-            }
+        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+        IAudioService audioService = IAudioService.Stub.asInterface(b);
+        try {
+            audioService.disableRingtoneSync(userContext.getUserId());
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to disable ringtone sync.");
         }
     }
 
@@ -851,22 +834,15 @@
      * @see #getActualDefaultRingtoneUri(Context, int)
      */
     public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
-        final ContentResolver resolver = context.getContentResolver();
-
-        if (Settings.Secure.getString(resolver, Settings.Secure.SYNC_PARENT_SOUNDS).equals("1")) {
-            // Sync is enabled, so we need to disable it
-            IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
-            IAudioService audioService = IAudioService.Stub.asInterface(b);
-            try {
-                audioService.disableRingtoneSync();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Unable to disable ringtone sync.");
-                return;
-            }
-        }
-
         String setting = getSettingForType(type);
         if (setting == null) return;
+
+        final ContentResolver resolver = context.getContentResolver();
+        if (Settings.Secure.getIntForUser(resolver, Settings.Secure.SYNC_PARENT_SOUNDS, 0,
+                    context.getUserId()) == 1) {
+            // Parent sound override is enabled. Disable it using the audio service.
+            disableSyncFromParent(context);
+        }
         if(!isInternalRingtoneUri(ringtoneUri)) {
             ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
         }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 85c153c..225b955 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -86,6 +86,7 @@
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
@@ -2615,6 +2616,8 @@
             if (isSecureSettingsKey(key)) {
                 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
                         sSecureCloneToManagedSettings);
+                maybeNotifyProfiles(SETTINGS_TYPE_SYSTEM, userId, uri, name,
+                        sSystemCloneFromParentOnDependency.values());
             } else if (isSystemSettingsKey(key)) {
                 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
                         sSystemCloneToManagedSettings);
@@ -2624,7 +2627,7 @@
         }
 
         private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
-                Set<String> keysCloned) {
+                Collection<String> keysCloned) {
             if (keysCloned.contains(name)) {
                 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
                     // the notification for userId has already been sent.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5b3495f..79b99a3 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6518,35 +6518,22 @@
         return mRecordMonitor.getActiveRecordingConfigurations();
     }
 
-    public void disableRingtoneSync() {
+    public void disableRingtoneSync(final int userId) {
         final int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId != userId) {
+            mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "disable sound settings syncing for another profile");
+        }
         final long token = Binder.clearCallingIdentity();
         try {
-            UserManager userManager = UserManager.get(mContext);
-
-            // Disable the sync setting
-            Settings.Secure.putIntForUser(mContentResolver,
-                    Settings.Secure.SYNC_PARENT_SOUNDS, 0 /* false */, callingUserId);
-
-            UserInfo parentInfo = userManager.getProfileParent(callingUserId);
-            if (parentInfo != null && parentInfo.id != callingUserId) {
-                // This is a managed profile, so we clone the ringtones from the parent profile
-                cloneRingtoneSetting(callingUserId, parentInfo.id, Settings.System.RINGTONE);
-                cloneRingtoneSetting(callingUserId, parentInfo.id,
-                        Settings.System.NOTIFICATION_SOUND);
-                cloneRingtoneSetting(callingUserId, parentInfo.id, Settings.System.ALARM_ALERT);
-            }
+            // Disable the sync setting so the profile uses its own sound settings.
+            Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
+                    0 /* false */, userId);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
-    private void cloneRingtoneSetting(int userId, int parentId, String ringtoneSetting) {
-        String parentSetting = Settings.System.getStringForUser(mContentResolver, ringtoneSetting,
-                parentId);
-        Settings.System.putStringForUser(mContentResolver, ringtoneSetting, parentSetting, userId);
-    }
-
     //======================
     // Audio playback notification
     //======================