Per-user content observer APIs

Callers with INTERACT_ACROSS_USERS_FULL permission can now observe content
for a given user's view (and can notify content uri changes targeted to a
specific user).  An observer watching for UserHandle.USER_ALL will see all
notifications for the given uri across all users; similarly, a notifier
who specifies USER_ALL will broadcast the change to all observers across
all users.

The API handles both USER_ALL or USER_CURRENT, and explicitly forbids
any other "pseudouser" designations.

This CL also revs the Settings provider to notify with USER_ALL for
changes to global settings, and with only the affected user's handle
for all other changes.

Bug 7122169

Change-Id: I94248b11aa91d1beb0a36432e82fe5725bb1264f
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 7cc5dec..a0ae9e3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -317,13 +317,14 @@
 
         boolean backedUpDataChanged = false;
         String property = null, table = uri.getPathSegments().get(0);
+        final boolean isGlobal = table.equals(TABLE_GLOBAL);
         if (table.equals(TABLE_SYSTEM)) {
             property = Settings.System.SYS_PROP_SETTING_VERSION + '_' + userHandle;
             backedUpDataChanged = true;
         } else if (table.equals(TABLE_SECURE)) {
             property = Settings.Secure.SYS_PROP_SETTING_VERSION + '_' + userHandle;
             backedUpDataChanged = true;
-        } else if (table.equals(TABLE_GLOBAL)) {
+        } else if (isGlobal) {
             property = Settings.Global.SYS_PROP_SETTING_VERSION;    // this one is global
             backedUpDataChanged = true;
         }
@@ -342,8 +343,9 @@
 
         String notify = uri.getQueryParameter("notify");
         if (notify == null || "true".equals(notify)) {
-            getContext().getContentResolver().notifyChange(uri, null);
-            if (LOCAL_LOGV) Log.v(TAG, "notifying: " + uri);
+            final int notifyTarget = isGlobal ? UserHandle.USER_ALL : userHandle;
+            getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
+            if (LOCAL_LOGV) Log.v(TAG, "notifying for " + notifyTarget + ": " + uri);
         } else {
             if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
         }