Pass userId through to singleton ContentProviders

System content providers like SettingsProvider run as singleUser but
on receipt of a call make decisions based on the calling user ID.

This is right up until the caller is a system service or a cross-user-
-aware app like Settings, where putStringForUser etc. provide a
workaround for most settings but not for the few files SettingsProvider
exposes.

Change-Id: I90060c9c13e274edd71f8a16ab3a026a58b98e3e
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index d27f1f8..7497fc1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -511,6 +511,13 @@
 
     @Override
     public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        final int userId = getUserIdFromUri(uri, UserHandle.getCallingUserId());
+        if (userId != UserHandle.getCallingUserId()) {
+            getContext().enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS,
+                    "Access files from the settings of another user");
+        }
+        uri = ContentProvider.getUriWithoutUserId(uri);
+
         final String cacheName;
         if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) {
             cacheName = Settings.System.RINGTONE_CACHE;
@@ -523,8 +530,7 @@
                     + "ringtone playback is available through android.media.Ringtone");
         }
 
-        final File cacheFile = new File(
-                getRingtoneCacheDir(UserHandle.getCallingUserId()), cacheName);
+        final File cacheFile = new File(getRingtoneCacheDir(userId), cacheName);
         return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode));
     }