1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app.backup;
18
19import android.app.QueuedWork;
20import android.content.Context;
21import android.content.SharedPreferences;
22import android.os.ParcelFileDescriptor;
23import android.util.Log;
24
25import java.io.File;
26
27/**
28 * A helper class that can be used in conjunction with
29 * {@link android.app.backup.BackupAgentHelper} to manage the backup of
30 * {@link android.content.SharedPreferences}. Whenever a backup is performed, it
31 * will back up all named shared preferences that have changed since the last
32 * backup operation.
33 * <p>
34 * To use this class, the application's backup agent class should extend
35 * {@link android.app.backup.BackupAgentHelper}.  Then, in the agent's
36 * {@link BackupAgent#onCreate()} method, an instance of this class should be
37 * allocated and installed as a backup/restore handler within the BackupAgentHelper
38 * framework.  For example, an agent supporting backup and restore for
39 * an application with two groups of {@link android.content.SharedPreferences}
40 * data might look something like this:
41 * <pre>
42 * import android.app.backup.BackupAgentHelper;
43 * import android.app.backup.SharedPreferencesBackupHelper;
44 *
45 * public class MyBackupAgent extends BackupAgentHelper {
46 *     // The names of the SharedPreferences groups that the application maintains.  These
47 *     // are the same strings that are passed to {@link Context#getSharedPreferences(String, int)}.
48 *     static final String PREFS_DISPLAY = "displayprefs";
49 *     static final String PREFS_SCORES = "highscores";
50 *
51 *     // An arbitrary string used within the BackupAgentHelper implementation to
52 *     // identify the SharedPreferenceBackupHelper's data.
53 *     static final String MY_PREFS_BACKUP_KEY = "myprefs";
54 *
55 *     // Simply allocate a helper and install it
56 *     void onCreate() {
57 *         SharedPreferencesBackupHelper helper =
58 *                 new SharedPreferencesBackupHelper(this, PREFS_DISPLAY, PREFS_SCORES);
59 *         addHelper(MY_PREFS_BACKUP_KEY, helper);
60 *     }
61 * }</pre>
62 * <p>
63 * No further implementation is needed; the {@link BackupAgentHelper} mechanism automatically
64 * dispatches the
65 * {@link BackupAgent#onBackup(android.os.ParcelFileDescriptor, BackupDataOutput, android.os.ParcelFileDescriptor) BackupAgent.onBackup()}
66 * and
67 * {@link BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) BackupAgent.onRestore()}
68 * callbacks to the SharedPreferencesBackupHelper as appropriate.
69 */
70public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper {
71    private static final String TAG = "SharedPreferencesBackupHelper";
72    private static final boolean DEBUG = false;
73
74    private Context mContext;
75    private String[] mPrefGroups;
76
77    /**
78     * Construct a helper for backing up and restoring the
79     * {@link android.content.SharedPreferences} under the given names.
80     *
81     * @param context The application {@link android.content.Context}
82     * @param prefGroups The names of each {@link android.content.SharedPreferences} file to
83     * back up
84     */
85    public SharedPreferencesBackupHelper(Context context, String... prefGroups) {
86        super(context);
87
88        mContext = context;
89        mPrefGroups = prefGroups;
90    }
91
92    /**
93     * Backs up the configured {@link android.content.SharedPreferences} groups.
94     */
95    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
96            ParcelFileDescriptor newState) {
97        Context context = mContext;
98
99        // If a SharedPreference has an outstanding write in flight,
100        // wait for it to finish flushing to disk.
101        QueuedWork.waitToFinish();
102
103        // make filenames for the prefGroups
104        String[] prefGroups = mPrefGroups;
105        final int N = prefGroups.length;
106        String[] files = new String[N];
107        for (int i=0; i<N; i++) {
108            files[i] = context.getSharedPrefsFile(prefGroups[i]).getAbsolutePath();
109        }
110
111        // go
112        performBackup_checked(oldState, data, newState, files, prefGroups);
113    }
114
115    /**
116     * Restores one entity from the restore data stream to its proper shared
117     * preferences file store.
118     */
119    public void restoreEntity(BackupDataInputStream data) {
120        Context context = mContext;
121
122        String key = data.getKey();
123        if (DEBUG) Log.d(TAG, "got entity '" + key + "' size=" + data.size());
124
125        if (isKeyInList(key, mPrefGroups)) {
126            File f = context.getSharedPrefsFile(key).getAbsoluteFile();
127            writeFile(f, data);
128        }
129    }
130}
131