Fix SharedPrefsBackupHelper so it doesn't hard code the paths to the files.

This took quite a bit of refactoring.
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 98bbf7b..fc3cdcf 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -300,10 +300,14 @@
         return new File(prefsFile.getPath() + ".bak");
     }
 
+    public File getSharedPrefsFile(String name) {
+        return makeFilename(getPreferencesDir(), name + ".xml");
+    }
+
     @Override
     public SharedPreferences getSharedPreferences(String name, int mode) {
         SharedPreferencesImpl sp;
-        File f = makeFilename(getPreferencesDir(), name + ".xml");
+        File f = getSharedPrefsFile(name);
         synchronized (sSharedPrefs) {
             sp = sSharedPrefs.get(f);
             if (sp != null && !sp.hasFileChanged()) {
diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java
index ec16eb1..99051bf 100644
--- a/core/java/android/backup/FileBackupHelper.java
+++ b/core/java/android/backup/FileBackupHelper.java
@@ -20,6 +20,7 @@
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
+import java.io.File;
 import java.io.FileDescriptor;
 
 /** @hide */
@@ -34,22 +35,34 @@
     public static void performBackup(Context context,
             ParcelFileDescriptor oldState, BackupDataOutput data,
             ParcelFileDescriptor newState, String[] files) {
-        String basePath = context.getFilesDir().getAbsolutePath();
-        performBackup_checked(basePath, oldState, data, newState, files);
+        File base = context.getFilesDir();
+        final int N = files.length;
+        String[] fullPaths = new String[N];
+        for (int i=0; i<N; i++) {
+            fullPaths[i] = (new File(base, files[i])).getAbsolutePath();
+        }
+        performBackup_checked(oldState, data, newState, fullPaths, files);
     }
 
     /**
      * Check the parameters so the native code doens't have to throw all the exceptions
      * since it's easier to do that from java.
      */
-    static void performBackup_checked(String basePath,
-            ParcelFileDescriptor oldState, BackupDataOutput data,
-            ParcelFileDescriptor newState, String[] files) {
+    static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState, String[] files, String[] keys) {
         if (files.length == 0) {
             return;
         }
-        if (basePath == null) {
-            throw new NullPointerException();
+        // files must be all absolute paths
+        for (String f: files) {
+            if (f.charAt(0) != '/') {
+                throw new RuntimeException("files must have all absolute paths: " + f);
+            }
+        }
+        // the length of files and keys must be the same
+        if (files.length != keys.length) {
+            throw new RuntimeException("files.length=" + files.length
+                    + " keys.length=" + keys.length);
         }
         // oldStateFd can be null
         FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
@@ -58,13 +71,14 @@
             throw new NullPointerException();
         }
 
-        int err = performBackup_native(basePath, oldStateFd, data.mBackupWriter, newStateFd, files);
+        int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
 
         if (err != 0) {
-            throw new RuntimeException("Backup failed"); // TODO: more here
+            // TODO: more here
+            throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
         }
     }
 
-    native private static int performBackup_native(String basePath, FileDescriptor oldState,
-            int data, FileDescriptor newState, String[] files);
+    native private static int performBackup_native(FileDescriptor oldState,
+            int data, FileDescriptor newState, String[] files, String[] keys);
 }
diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java
index 8627f08..923dc1b 100644
--- a/core/java/android/backup/SharedPreferencesBackupHelper.java
+++ b/core/java/android/backup/SharedPreferencesBackupHelper.java
@@ -26,16 +26,14 @@
     public static void performBackup(Context context,
             ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot,
             BackupDataOutput data, String[] prefGroups) {
-        String basePath = "/xxx"; //context.getPreferencesDir();
-
         // make filenames for the prefGroups
         final int N = prefGroups.length;
         String[] files = new String[N];
         for (int i=0; i<N; i++) {
-            files[i] = prefGroups[i] + ".xml";
+            files[i] = context.getSharedPrefsFile(prefGroups[i]).toString();
         }
 
-        FileBackupHelper.performBackup_checked(basePath, oldSnapshot, data, newSnapshot, files);
+        FileBackupHelper.performBackup_checked(oldSnapshot, data, newSnapshot, files, prefGroups);
     }
 }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ec847a4..925249e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -254,12 +254,20 @@
      * <p>Note: this is not generally useful for applications, since they should
      * not be directly accessing the file system.
      *
-     *
      * @return String Path to the code and assets.
      */
     public abstract String getPackageCodePath();
 
     /**
+     * {@hide}
+     * Return the full path to the shared prefs file for the given prefs group name.
+     *
+     * <p>Note: this is not generally useful for applications, since they should
+     * not be directly accessing the file system.
+     */
+    public abstract File getSharedPrefsFile(String name);
+
+    /**
      * Retrieve and hold the contents of the preferences file 'name', returning
      * a SharedPreferences through which you can retrieve and modify its
      * values.  Only one instance of the SharedPreferences object is returned
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 36e1c34..262204e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -130,6 +130,11 @@
     }
 
     @Override
+    public File getSharedPrefsFile(String name) {
+        return mBase.getSharedPrefsFile(name);
+    }
+
+    @Override
     public SharedPreferences getSharedPreferences(String name, int mode) {
         return mBase.getSharedPreferences(name, mode);
     }
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp
index a46f37b..2ee064b 100644
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ b/core/jni/android_backup_FileBackupHelper.cpp
@@ -28,8 +28,8 @@
 static jfieldID s_descriptorField = 0;
 
 static int
-performBackup_native(JNIEnv* env, jobject clazz, jstring basePath, jobject oldState, int data,
-        jobject newState, jobjectArray files)
+performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data,
+        jobject newState, jobjectArray files, jobjectArray keys)
 {
     int err;
 
@@ -39,29 +39,37 @@
     int newStateFD = env->GetIntField(newState, s_descriptorField);
     BackupDataWriter* dataStream = (BackupDataWriter*)data;
 
-    char const* basePathUTF = env->GetStringUTFChars(basePath, NULL);
-    LOGD("basePathUTF=\"%s\"\n", basePathUTF);
     const int fileCount = env->GetArrayLength(files);
     char const** filesUTF = (char const**)malloc(sizeof(char*)*fileCount);
     for (int i=0; i<fileCount; i++) {
         filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL);
     }
 
-    err = back_up_files(oldStateFD, dataStream, newStateFD, basePathUTF, filesUTF, fileCount);
+    const int keyCount = env->GetArrayLength(keys);
+    char const** keysUTF = (char const**)malloc(sizeof(char*)*keyCount);
+    for (int i=0; i<keyCount; i++) {
+        keysUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(keys, i), NULL);
+    }
+
+    err = back_up_files(oldStateFD, dataStream, newStateFD, filesUTF, keysUTF, fileCount);
 
     for (int i=0; i<fileCount; i++) {
         env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]);
     }
     free(filesUTF);
-    env->ReleaseStringUTFChars(basePath, basePathUTF);
+
+    for (int i=0; i<keyCount; i++) {
+        env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(keys, i), keysUTF[i]);
+    }
+    free(keysUTF);
 
     return err;
 }
 
 static const JNINativeMethod g_methods[] = {
     { "performBackup_native",
-        "(Ljava/lang/String;Ljava/io/FileDescriptor;ILjava/io/FileDescriptor;[Ljava/lang/String;)I",
-        (void*)performBackup_native },
+       "(Ljava/io/FileDescriptor;ILjava/io/FileDescriptor;[Ljava/lang/String;[Ljava/lang/String;)I",
+       (void*)performBackup_native },
 };
 
 int register_android_backup_FileBackupHelper(JNIEnv* env)