Only restore the bits for wallpapers that aren't built in.
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 1e4ab68..b095e30 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -578,7 +578,7 @@
     @Override
     public void setWallpaper(Bitmap bitmap) throws IOException  {
         try {
-            ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
+            ParcelFileDescriptor fd = getWallpaperService().setWallpaper(null);
             if (fd == null) {
                 return;
             }
@@ -598,7 +598,7 @@
     @Override
     public void setWallpaper(InputStream data) throws IOException {
         try {
-            ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
+            ParcelFileDescriptor fd = getWallpaperService().setWallpaper(null);
             if (fd == null) {
                 return;
             }
@@ -627,13 +627,16 @@
     @Override
     public void clearWallpaper() throws IOException {
         try {
+            Resources resources = getResources();
             /* Set the wallpaper to the default values */
-            ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
+            ParcelFileDescriptor fd = getWallpaperService().setWallpaper(
+                    "res:" + resources.getResourceName(
+                        com.android.internal.R.drawable.default_wallpaper));
             if (fd != null) {
                 FileOutputStream fos = null;
                 try {
                     fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-                    setWallpaper(getResources().openRawResource(
+                    setWallpaper(resources.openRawResource(
                             com.android.internal.R.drawable.default_wallpaper),
                             fos);
                 } finally {
diff --git a/core/java/android/app/IWallpaperService.aidl b/core/java/android/app/IWallpaperService.aidl
index a332b1a..281a060 100644
--- a/core/java/android/app/IWallpaperService.aidl
+++ b/core/java/android/app/IWallpaperService.aidl
@@ -25,7 +25,7 @@
     /**
      * Set the wallpaper.
      */
-    ParcelFileDescriptor setWallpaper();
+    ParcelFileDescriptor setWallpaper(String name);
     
     /**
      * Get the wallpaper.
diff --git a/core/java/android/backup/BackupDataInput.java b/core/java/android/backup/BackupDataInput.java
index 69c206c..e67b0be 100644
--- a/core/java/android/backup/BackupDataInput.java
+++ b/core/java/android/backup/BackupDataInput.java
@@ -97,12 +97,7 @@
 
     public void skipEntityData() throws IOException {
         if (mHeaderReady) {
-            int result = skipEntityData_native(mBackupReader);
-            if (result >= 0) {
-                return;
-            } else {
-                throw new IOException("result=0x" + Integer.toHexString(result));
-            }
+            skipEntityData_native(mBackupReader);
         } else {
             throw new IllegalStateException("mHeaderReady=false");
         }
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index d9804ea..38d252e 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -25,22 +25,35 @@
 import java.util.HashMap;
 
 public abstract class FileObserver {
-    public static final int ACCESS = 0x00000001; /* File was accessed */
-    public static final int MODIFY = 0x00000002; /* File was modified */
-    public static final int ATTRIB = 0x00000004; /* Metadata changed */
-    public static final int CLOSE_WRITE = 0x00000008; /*  Writtable file was  closed */
-    public static final int CLOSE_NOWRITE = 0x00000010; /* Unwrittable file closed */
-    public static final int OPEN = 0x00000020; /* File was opened */
-    public static final int MOVED_FROM = 0x00000040; /* File was moved from X */
-    public static final int MOVED_TO = 0x00000080; /* File was moved to Y */
-    public static final int CREATE = 0x00000100; /* Subfile was created */
-    public static final int DELETE = 0x00000200; /* Subfile was deleted */
-    public static final int DELETE_SELF = 0x00000400; /* Self was deleted */
-    public static final int MOVE_SELF = 0x00000800; /* Self was moved */
+    /** File was accessed */
+    public static final int ACCESS = 0x00000001;
+    /** File was modified */
+    public static final int MODIFY = 0x00000002;
+    /** Metadata changed */
+    public static final int ATTRIB = 0x00000004;
+    /** Writable file was closed */
+    public static final int CLOSE_WRITE = 0x00000008;
+    /** Unwrittable file closed */
+    public static final int CLOSE_NOWRITE = 0x00000010;
+    /** File was opened */
+    public static final int OPEN = 0x00000020;
+    /** File was moved from X */
+    public static final int MOVED_FROM = 0x00000040;
+    /** File was moved to Y */
+    public static final int MOVED_TO = 0x00000080;
+    /** Subfile was created */
+    public static final int CREATE = 0x00000100;
+    /** Subfile was deleted */
+    public static final int DELETE = 0x00000200;
+    /** Self was deleted */
+    public static final int DELETE_SELF = 0x00000400;
+    /** Self was moved */
+    public static final int MOVE_SELF = 0x00000800;
+
     public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE 
             | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
 	    | DELETE_SELF | MOVE_SELF;
-    
+
     private static final String LOG_TAG = "FileObserver";
 
     private static class ObserverThread extends Thread {
diff --git a/core/java/com/android/internal/backup/SystemBackupAgent.java b/core/java/com/android/internal/backup/SystemBackupAgent.java
deleted file mode 100644
index 6b396d7..0000000
--- a/core/java/com/android/internal/backup/SystemBackupAgent.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.backup;
-
-import android.backup.AbsoluteFileBackupHelper;
-import android.backup.BackupHelperAgent;
-
-/**
- * Backup agent for various system-managed data
- */
-public class SystemBackupAgent extends BackupHelperAgent {
-    // the set of files that we back up whole, as absolute paths
-    String[] mFiles = {
-            /* WallpaperService.WALLPAPER_FILE */
-            "/data/data/com.android.settings/files/wallpaper",
-            };
-
-    public void onCreate() {
-        addHelper("system_files", new AbsoluteFileBackupHelper(this, mFiles));
-    }
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6ad2441..1cd04f1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1087,7 +1087,7 @@
                  android:hasCode="false"
                  android:label="@string/android_system_label"
                  android:allowClearUserData="false"
-                 android:backupAgent="com.android.internal.backup.SystemBackupAgent"
+                 android:backupAgent="com.android.server.SystemBackupAgent"
                  android:icon="@drawable/ic_launcher_android">
         <activity android:name="com.android.internal.app.ChooserActivity"
                 android:theme="@style/Theme.Dialog.Alert"
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index c51d989..0cef35a 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -193,6 +193,7 @@
         if ((actual) != (expected)) { \
             if ((actual) == 0) { \
                 m_status = EIO; \
+                m_done = true; \
             } else { \
                 m_status = errno; \
             } \
@@ -222,7 +223,7 @@
 
     amt = skip_padding();
     if (amt == EIO) {
-        *done = true;
+        *done = m_done = true;
         return NO_ERROR;
     }
     else if (amt != NO_ERROR) {
@@ -338,6 +339,10 @@
         m_status = errno;
         return -1;
     }
+    if (amt == 0) {
+        m_status = EIO;
+        m_done = true;
+    }
     m_pos += amt;
     return amt;
 }
diff --git a/services/java/com/android/server/JournaledFile.java b/services/java/com/android/server/JournaledFile.java
new file mode 100644
index 0000000..3d1f52d
--- /dev/null
+++ b/services/java/com/android/server/JournaledFile.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import java.io.File;
+import java.io.IOException;
+
+public class JournaledFile {
+    File mReal;
+    File mTemp;
+    boolean mWriting;
+
+    public JournaledFile(File real, File temp) {
+        mReal = real;
+        mTemp = temp;
+    }
+
+    /** Returns the file for you to read.
+     * @more
+     * Prefers the real file.  If it doesn't exist, uses the temp one, and then copies
+     * it to the real one.  If there is both a real file and a temp one, assumes that the
+     * temp one isn't fully written and deletes it.
+     */
+    public File chooseForRead() {
+        File result;
+        if (mReal.exists()) {
+            result = mReal;
+            if (mTemp.exists()) {
+                mTemp.delete();
+            }
+        } else if (mTemp.exists()) {
+            result = mTemp;
+            mTemp.renameTo(mReal);
+        } else {
+            return mReal;
+        }
+        return result;
+    }
+
+    /**
+     * Returns a file for you to write.
+     * @more
+     * If a write is already happening, throws.  In other words, you must provide your
+     * own locking.
+     * <p>
+     * Call {@link #commit} to commit the changes, or {@link #rollback} to forget the changes.
+     */
+    public File chooseForWrite() {
+        if (mWriting) {
+            throw new IllegalStateException("uncommitted write already in progress");
+        }
+        if (!mReal.exists()) {
+            // If the real one doesn't exist, it's either because this is the first time
+            // or because something went wrong while copying them.  In this case, we can't
+            // trust anything that's in temp.  In order to have the chooseForRead code not
+            // use the temporary one until it's fully written, create an empty file
+            // for real, which will we'll shortly delete.
+            try {
+                mReal.createNewFile();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+
+        if (mTemp.exists()) {
+            mTemp.delete();
+        }
+        mWriting = true;
+        return mTemp;
+    }
+
+    /**
+     * Commit changes.
+     */
+    public void commit() {
+        if (!mWriting) {
+            throw new IllegalStateException("no file to commit");
+        }
+        mWriting = false;
+        mTemp.renameTo(mReal);
+    }
+
+    /**
+     * Roll back changes.
+     */
+    public void rollback() {
+        if (!mWriting) {
+            throw new IllegalStateException("no file to roll back");
+        }
+        mWriting = false;
+        mTemp.delete();
+    }
+}
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
new file mode 100644
index 0000000..b681961
--- /dev/null
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.backup.AbsoluteFileBackupHelper;
+import android.backup.BackupDataInput;
+import android.backup.BackupDataInputStream;
+import android.backup.BackupDataOutput;
+import android.backup.BackupHelper;
+import android.backup.BackupHelperAgent;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.os.ServiceManager;
+import android.os.SystemService;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Backup agent for various system-managed data
+ */
+public class SystemBackupAgent extends BackupHelperAgent {
+    private static final String TAG = "SystemBackupAgent";
+
+    private static final String WALLPAPER_IMAGE = "/data/data/com.android.settings/files/wallpaper";
+    private static final String WALLPAPER_INFO = "/data/system/wallpaper_info.xml";
+
+    @Override
+    public void onCreate() {
+        addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+                new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }));
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        boolean success = false;
+        try {
+            super.onRestore(data, appVersionCode, newState);
+
+            WallpaperService wallpaper = (WallpaperService)ServiceManager.getService(
+                    Context.WALLPAPER_SERVICE);
+            wallpaper.settingsRestored();
+        } catch (IOException ex) {
+            // If there was a failure, delete everything for the wallpaper, this is too aggresive,
+            // but this is hopefully a rare failure.
+            Log.d(TAG, "restore failed", ex);
+            (new File(WALLPAPER_IMAGE)).delete();
+            (new File(WALLPAPER_INFO)).delete();
+        }
+    }
+}
diff --git a/services/java/com/android/server/WallpaperService.java b/services/java/com/android/server/WallpaperService.java
index d921baf..11981df 100644
--- a/services/java/com/android/server/WallpaperService.java
+++ b/services/java/com/android/server/WallpaperService.java
@@ -24,8 +24,9 @@
 import android.backup.BackupManager;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.FileObserver;
@@ -33,30 +34,38 @@
 import android.os.RemoteCallbackList;
 import android.util.Config;
 import android.util.Log;
+import android.util.Xml;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import com.android.internal.util.FastXmlSerializer;
 
 class WallpaperService extends IWallpaperService.Stub {
-    private static final String TAG = WallpaperService.class.getSimpleName();     
+    private static final String TAG = "WallpaperService";
+
+    private Object mLock = new Object();
 
     private static final File WALLPAPER_DIR = new File(
             "/data/data/com.android.settings/files");
     private static final String WALLPAPER = "wallpaper";
     private static final File WALLPAPER_FILE = new File(WALLPAPER_DIR, WALLPAPER);
 
-    private static final String PREFERENCES = "wallpaper-hints";
-
-    private static final String HINT_WIDTH = "hintWidth";
-    private static final String HINT_HEIGHT = "hintHeight";
-
     /**
      * List of callbacks registered they should each be notified
      * when the wallpaper is changed.
      */
     private final RemoteCallbackList<IWallpaperServiceCallback> mCallbacks
             = new RemoteCallbackList<IWallpaperServiceCallback>();
-    
+
     /**
      * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
      * that the wallpaper has changed. The CREATE is triggered when there is no
@@ -64,16 +73,24 @@
      * everytime the wallpaper is changed.
      */
     private final FileObserver mWallpaperObserver = new FileObserver(
-            WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE) {
+            WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE | DELETE | DELETE_SELF) {
                 @Override
                 public void onEvent(int event, String path) {
-                    if (path == null) {
-                        return;
-                    }
+                    synchronized (mLock) {
+                        if (path == null) {
+                            return;
+                        }
 
-                    File changedFile = new File(WALLPAPER_DIR, path);
-                    if (WALLPAPER_FILE.equals(changedFile)) {
-                        notifyCallbacks();
+                        // changing the wallpaper means we'll need to back up the new one
+                        long origId = Binder.clearCallingIdentity();
+                        BackupManager bm = new BackupManager(mContext);
+                        bm.dataChanged();
+                        Binder.restoreCallingIdentity(origId);
+
+                        File changedFile = new File(WALLPAPER_DIR, path);
+                        if (WALLPAPER_FILE.equals(changedFile)) {
+                            notifyCallbacksLocked();
+                        }
                     }
                 }
             };
@@ -82,17 +99,16 @@
 
     private int mWidth = -1;
     private int mHeight = -1;
+    private String mName = "";
 
     public WallpaperService(Context context) {
         if (Config.LOGD) Log.d(TAG, "WallpaperService startup");
         mContext = context;
-        createFilesDir();
+        if (!WALLPAPER_DIR.exists()) {
+            WALLPAPER_DIR.mkdirs();
+        }
         mWallpaperObserver.startWatching();
-
-        SharedPreferences preferences = mContext.getSharedPreferences(PREFERENCES,
-                    Context.MODE_PRIVATE);
-        mWidth = preferences.getInt(HINT_WIDTH, -1);
-        mHeight = preferences.getInt(HINT_HEIGHT, -1);
+        loadSettingsLocked();
     }
     
     @Override
@@ -102,9 +118,11 @@
     }
     
     public void clearWallpaper() {
-        File f = WALLPAPER_FILE;
-        if (f.exists()) {
-            f.delete();
+        synchronized (mLock) {
+            File f = WALLPAPER_FILE;
+            if (f.exists()) {
+                f.delete();
+            }
         }
     }
 
@@ -115,70 +133,62 @@
             throw new IllegalArgumentException("width and height must be > 0");
         }
 
-        if (width != mWidth || height != mHeight) {
-            mWidth = width;
-            mHeight = height;
-
-            SharedPreferences preferences = mContext.getSharedPreferences(PREFERENCES,
-                    Context.MODE_PRIVATE);
-
-            final SharedPreferences.Editor editor = preferences.edit();
-            editor.putInt(HINT_WIDTH, width);
-            editor.putInt(HINT_HEIGHT, height);
-            editor.commit();
+        synchronized (mLock) {
+            if (width != mWidth || height != mHeight) {
+                mWidth = width;
+                mHeight = height;
+                saveSettingsLocked();
+            }
         }
     }
 
     public int getWidthHint() throws RemoteException {
-        return mWidth;
+        synchronized (mLock) {
+            return mWidth;
+        }
     }
 
     public int getHeightHint() throws RemoteException {
-        return mHeight;
+        synchronized (mLock) {
+            return mHeight;
+        }
     }
 
     public ParcelFileDescriptor getWallpaper(IWallpaperServiceCallback cb) {
-        try {
-            mCallbacks.register(cb);
-            File f = WALLPAPER_FILE;
-            if (!f.exists()) {
-                return null;
+        synchronized (mLock) {
+            try {
+                mCallbacks.register(cb);
+                File f = WALLPAPER_FILE;
+                if (!f.exists()) {
+                    return null;
+                }
+                return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
+            } catch (FileNotFoundException e) {
+                /* Shouldn't happen as we check to see if the file exists */
+                if (Config.LOGD) Log.d(TAG, "Error getting wallpaper", e);
             }
-            return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
-        } catch (FileNotFoundException e) {
-            
-            /* Shouldn't happen as we check to see if the file exists */
-            if (Config.LOGD) Log.d(TAG, "Error getting wallpaper", e);
+            return null;
         }
-        return null;
     }
 
-    public ParcelFileDescriptor setWallpaper() {
+    public ParcelFileDescriptor setWallpaper(String name) {
         checkPermission(android.Manifest.permission.SET_WALLPAPER);
-        try {
-            ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
-                    MODE_CREATE|MODE_READ_WRITE);
-
-            // changing the wallpaper means we'll need to back up the new one
-            long origId = Binder.clearCallingIdentity();
-            BackupManager bm = new BackupManager(mContext);
-            bm.dataChanged();
-            Binder.restoreCallingIdentity(origId);
-
-            return fd;
-        } catch (FileNotFoundException e) {
-            if (Config.LOGD) Log.d(TAG, "Error setting wallpaper", e);
-        }
-        return null;
-    }
-
-    private void createFilesDir() {
-        if (!WALLPAPER_DIR.exists()) {
-            WALLPAPER_DIR.mkdirs();
+        synchronized (mLock) {
+            if (name == null) name = "";
+            mName = name;
+            saveSettingsLocked();
+            try {
+                ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
+                        MODE_CREATE|MODE_READ_WRITE);
+                return fd;
+            } catch (FileNotFoundException e) {
+                if (Config.LOGD) Log.d(TAG, "Error setting wallpaper", e);
+            }
+            return null;
         }
     }
 
-    private void notifyCallbacks() {
+    private void notifyCallbacksLocked() {
         final int n = mCallbacks.beginBroadcast();
         for (int i = 0; i < n; i++) {
             try {
@@ -195,9 +205,185 @@
     }
 
     private void checkPermission(String permission) {
-        if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) {
+        if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
             throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
                     + ", must have permission " + permission);
         }
     }
+
+    private static JournaledFile makeJournaledFile() {
+        final String base = "/data/system/wallpaper_info.xml";
+        return new JournaledFile(new File(base), new File(base + ".tmp"));
+    }
+
+    private void saveSettingsLocked() {
+        JournaledFile journal = makeJournaledFile();
+        FileOutputStream stream = null;
+        try {
+            stream = new FileOutputStream(journal.chooseForWrite(), false);
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(stream, "utf-8");
+            out.startDocument(null, true);
+
+            out.startTag(null, "wp");
+            out.attribute(null, "width", Integer.toString(mWidth));
+            out.attribute(null, "height", Integer.toString(mHeight));
+            out.attribute(null, "name", mName);
+            out.endTag(null, "wp");
+
+            out.endDocument();
+            stream.close();
+            journal.commit();
+        } catch (IOException e) {
+            try {
+                if (stream != null) {
+                    stream.close();
+                }
+            } catch (IOException ex) {
+                // Ignore
+            }
+            journal.rollback();
+        }
+    }
+
+    private void loadSettingsLocked() {
+        JournaledFile journal = makeJournaledFile();
+        FileInputStream stream = null;
+        File file = journal.chooseForRead();
+        boolean success = false;
+        try {
+            stream = new FileInputStream(file);
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(stream, null);
+
+            int type;
+            int providerIndex = 0;
+            do {
+                type = parser.next();
+                if (type == XmlPullParser.START_TAG) {
+                    String tag = parser.getName();
+                    if ("wp".equals(tag)) {
+                        mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
+                        mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
+                        mName = parser.getAttributeValue(null, "name");
+                    }
+                }
+            } while (type != XmlPullParser.END_DOCUMENT);
+            success = true;
+        } catch (NullPointerException e) {
+            Log.w(TAG, "failed parsing " + file, e);
+        } catch (NumberFormatException e) {
+            Log.w(TAG, "failed parsing " + file, e);
+        } catch (XmlPullParserException e) {
+            Log.w(TAG, "failed parsing " + file, e);
+        } catch (IOException e) {
+            Log.w(TAG, "failed parsing " + file, e);
+        } catch (IndexOutOfBoundsException e) {
+            Log.w(TAG, "failed parsing " + file, e);
+        }
+        try {
+            if (stream != null) {
+                stream.close();
+            }
+        } catch (IOException e) {
+            // Ignore
+        }
+
+        if (!success) {
+            mWidth = -1;
+            mHeight = -1;
+            mName = "";
+        }
+    }
+
+    void settingsRestored() {
+        boolean success = false;
+        synchronized (mLock) {
+            loadSettingsLocked();
+            // If there's a wallpaper name, we use that.  If that can't be loaded, then we
+            // use the default.
+            if ("".equals(mName)) {
+                success = true;
+            } else {
+                success = restoreNamedResourceLocked();
+            }
+        }
+
+        if (!success) {
+            Log.e(TAG, "Failed to restore wallpaper: '" + mName + "'");
+            mName = "";
+            WALLPAPER_FILE.delete();
+        }
+        saveSettingsLocked();
+    }
+
+    boolean restoreNamedResourceLocked() {
+        if (mName.length() > 4 && "res:".equals(mName.substring(0, 4))) {
+            String resName = mName.substring(4);
+
+            String pkg = null;
+            int colon = resName.indexOf(':');
+            if (colon > 0) {
+                pkg = resName.substring(0, colon);
+            }
+
+            String ident = null;
+            int slash = resName.lastIndexOf('/');
+            if (slash > 0) {
+                ident = resName.substring(slash+1);
+            }
+
+            String type = null;
+            if (colon > 0 && slash > 0 && (slash-colon) > 1) {
+                type = resName.substring(colon+1, slash);
+            }
+
+            if (pkg != null && ident != null && type != null) {
+                int resId = -1;
+                InputStream res = null;
+                FileOutputStream fos = null;
+                try {
+                    Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
+                    Resources r = c.getResources();
+                    resId = r.getIdentifier(resName, null, null);
+                    if (resId == 0) {
+                        Log.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
+                                + " ident=" + ident);
+                        return false;
+                    }
+
+                    res = r.openRawResource(resId);
+                    fos = new FileOutputStream(WALLPAPER_FILE);
+
+                    byte[] buffer = new byte[32768];
+                    int amt;
+                    while ((amt=res.read(buffer)) > 0) {
+                        fos.write(buffer, 0, amt);
+                    }
+                    // mWallpaperObserver will notice the close and send the change broadcast
+
+                    Log.d(TAG, "Restored wallpaper: " + resName);
+                    return true;
+                } catch (NameNotFoundException e) {
+                    Log.e(TAG, "Package name " + pkg + " not found");
+                } catch (Resources.NotFoundException e) {
+                    Log.e(TAG, "Resource not found: " + resId);
+                } catch (IOException e) {
+                    Log.e(TAG, "IOException while restoring wallpaper ", e);
+                } finally {
+                    if (res != null) {
+                        try {
+                            res.close();
+                        } catch (IOException ex) {}
+                    }
+                    if (fos != null) {
+                        try {
+                            fos.close();
+                        } catch (IOException ex) {}
+                    }
+                }
+            }
+        }
+        return false;
+    }
 }