Notify all running users for global settings change

Test: pass: atest android.provider.cts.SettingsTest
      pass: atest android.provider.cts.Settings_SystemTest
      pass: atest android.provider.cts.Settings_SecureTest
      pass: adb shell am instrument -w com.android.providers.setting.test
                /android.support.test.runner.AndroidJUnitRunner

Bug: 74547258

Change-Id: Ic8c76467248d5bea64eeb8c7321f552664b6a2a6
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index b37071b..4054d5e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2750,31 +2750,34 @@
         }
 
         private void notifyForSettingsChange(int key, String name) {
-            final int userId = getUserIdFromKey(key);
-            Uri uri = getNotificationUriFor(key, name);
-
+            // Increment the generation first, so observers always see the new value
             mGenerationRegistry.incrementGeneration(key);
 
-            mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
-                    userId, 0, uri).sendToTarget();
-
-            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);
+            if (isGlobalSettingsKey(key)) {
+                if (Global.LOCATION_GLOBAL_KILL_SWITCH.equals(name)) {
+                    // When the global kill switch is updated, send the
+                    // change notification for the location setting.
+                    notifyLocationChangeForRunningUsers();
+                }
+                notifyGlobalSettingChangeForRunningUsers(key, name);
+            } else {
+                final int userId = getUserIdFromKey(key);
+                final Uri uri = getNotificationUriFor(key, name);
+                mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
+                        userId, 0, uri).sendToTarget();
+                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);
+                }
             }
 
+            // Always notify that our data changed
             mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
-
-            // When the global kill switch is updated, send the change notification for
-            // the location setting.
-            if (isGlobalSettingsKey(key) && Global.LOCATION_GLOBAL_KILL_SWITCH.equals(name)) {
-                notifyLocationChangeForRunningUsers();
-            }
         }
 
         private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
@@ -2783,33 +2786,46 @@
                 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
                     // the notification for userId has already been sent.
                     if (profileId != userId) {
+                        final int key = makeKey(type, profileId);
+                        // Increment the generation first, so observers always see the new value
+                        mGenerationRegistry.incrementGeneration(key);
                         mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
                                 profileId, 0, uri).sendToTarget();
-                        final int key = makeKey(type, profileId);
-                        mGenerationRegistry.incrementGeneration(key);
-
-                        mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
                     }
                 }
             }
         }
 
+        private void notifyGlobalSettingChangeForRunningUsers(int key, String name) {
+            // Important: No need to update generation for each user as there
+            // is a singleton generation entry for the global settings which
+            // is already incremented be the caller.
+            final Uri uri = getNotificationUriFor(key, name);
+            final List<UserInfo> users = mUserManager.getUsers(/*excludeDying*/ true);
+            for (int i = 0; i < users.size(); i++) {
+                final int userId = users.get(i).id;
+                if (mUserManager.isUserRunning(UserHandle.of(userId))) {
+                    mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
+                            userId, 0, uri).sendToTarget();
+                }
+            }
+        }
+
         private void notifyLocationChangeForRunningUsers() {
             final List<UserInfo> users = mUserManager.getUsers(/*excludeDying=*/ true);
 
             for (int i = 0; i < users.size(); i++) {
                 final int userId = users.get(i).id;
 
-                // Do we have to increment the generation for users that are not running?
-                // Yeah let's assume so...
-                final int key = makeKey(SETTINGS_TYPE_SECURE, userId);
-                mGenerationRegistry.incrementGeneration(key);
-
                 if (!mUserManager.isUserRunning(UserHandle.of(userId))) {
                     continue;
                 }
-                final Uri uri = getNotificationUriFor(key, Secure.LOCATION_PROVIDERS_ALLOWED);
 
+                // Increment the generation first, so observers always see the new value
+                final int key = makeKey(SETTINGS_TYPE_SECURE, userId);
+                mGenerationRegistry.incrementGeneration(key);
+
+                final Uri uri = getNotificationUriFor(key, Secure.LOCATION_PROVIDERS_ALLOWED);
                 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
                         userId, 0, uri).sendToTarget();
             }