• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server;
18 
19 
20 import android.app.backup.BackupDataInput;
21 import android.app.backup.BackupDataOutput;
22 import android.app.backup.BackupAgentHelper;
23 import android.app.backup.FullBackup;
24 import android.app.backup.FullBackupDataOutput;
25 import android.app.backup.WallpaperBackupHelper;
26 import android.content.Context;
27 import android.os.Environment;
28 import android.os.ParcelFileDescriptor;
29 import android.os.ServiceManager;
30 import android.os.UserHandle;
31 import android.util.Slog;
32 
33 
34 import java.io.File;
35 import java.io.IOException;
36 
37 /**
38  * Backup agent for various system-managed data, currently just the system wallpaper
39  */
40 public class SystemBackupAgent extends BackupAgentHelper {
41     private static final String TAG = "SystemBackupAgent";
42 
43     // These paths must match what the WallpaperManagerService uses.  The leaf *_FILENAME
44     // are also used in the full-backup file format, so must not change unless steps are
45     // taken to support the legacy backed-up datasets.
46     private static final String WALLPAPER_IMAGE_FILENAME = "wallpaper";
47     private static final String WALLPAPER_INFO_FILENAME = "wallpaper_info.xml";
48 
49     // TODO: Will need to change if backing up non-primary user's wallpaper
50     private static final String WALLPAPER_IMAGE_DIR =
51             Environment.getUserSystemDirectory(UserHandle.USER_OWNER).getAbsolutePath();
52     private static final String WALLPAPER_IMAGE = WallpaperBackupHelper.WALLPAPER_IMAGE;
53 
54     // TODO: Will need to change if backing up non-primary user's wallpaper
55     private static final String WALLPAPER_INFO_DIR =
56             Environment.getUserSystemDirectory(UserHandle.USER_OWNER).getAbsolutePath();
57     private static final String WALLPAPER_INFO = WallpaperBackupHelper.WALLPAPER_INFO;
58     // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
59     private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
60     private static final String WALLPAPER_INFO_KEY = WallpaperBackupHelper.WALLPAPER_INFO_KEY;
61 
62     @Override
onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)63     public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
64             ParcelFileDescriptor newState) throws IOException {
65         // We only back up the data under the current "wallpaper" schema with metadata
66         WallpaperManagerService wallpaper = (WallpaperManagerService)ServiceManager.getService(
67                 Context.WALLPAPER_SERVICE);
68         String[] files = new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO };
69         String[] keys = new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY };
70         if (wallpaper != null && wallpaper.getName() != null && wallpaper.getName().length() > 0) {
71             // When the wallpaper has a name, back up the info by itself.
72             // TODO: Don't rely on the innards of the service object like this!
73             // TODO: Send a delete for any stored wallpaper image in this case?
74             files = new String[] { WALLPAPER_INFO };
75             keys = new String[] { WALLPAPER_INFO_KEY };
76         }
77         addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this, files, keys));
78         super.onBackup(oldState, data, newState);
79     }
80 
81     @Override
onFullBackup(FullBackupDataOutput data)82     public void onFullBackup(FullBackupDataOutput data) throws IOException {
83         // At present we back up only the wallpaper
84         fullWallpaperBackup(data);
85     }
86 
fullWallpaperBackup(FullBackupDataOutput output)87     private void fullWallpaperBackup(FullBackupDataOutput output) {
88         // Back up the data files directly.  We do them in this specific order --
89         // info file followed by image -- because then we need take no special
90         // steps during restore; the restore will happen properly when the individual
91         // files are restored piecemeal.
92         FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null,
93                 WALLPAPER_INFO_DIR, WALLPAPER_INFO, output.getData());
94         FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null,
95                 WALLPAPER_IMAGE_DIR, WALLPAPER_IMAGE, output.getData());
96     }
97 
98     @Override
onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)99     public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
100             throws IOException {
101         // On restore, we also support a previous data schema "system_files"
102         addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this,
103                 new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO },
104                 new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY} ));
105         addHelper("system_files", new WallpaperBackupHelper(SystemBackupAgent.this,
106                 new String[] { WALLPAPER_IMAGE },
107                 new String[] { WALLPAPER_IMAGE_KEY} ));
108 
109         try {
110             super.onRestore(data, appVersionCode, newState);
111 
112             WallpaperManagerService wallpaper = (WallpaperManagerService)ServiceManager.getService(
113                     Context.WALLPAPER_SERVICE);
114             wallpaper.settingsRestored();
115         } catch (IOException ex) {
116             // If there was a failure, delete everything for the wallpaper, this is too aggressive,
117             // but this is hopefully a rare failure.
118             Slog.d(TAG, "restore failed", ex);
119             (new File(WALLPAPER_IMAGE)).delete();
120             (new File(WALLPAPER_INFO)).delete();
121         }
122     }
123 
124     @Override
onRestoreFile(ParcelFileDescriptor data, long size, int type, String domain, String path, long mode, long mtime)125     public void onRestoreFile(ParcelFileDescriptor data, long size,
126             int type, String domain, String path, long mode, long mtime)
127             throws IOException {
128         Slog.i(TAG, "Restoring file domain=" + domain + " path=" + path);
129 
130         // Bits to indicate postprocessing we may need to perform
131         boolean restoredWallpaper = false;
132 
133         File outFile = null;
134         // Various domain+files we understand a priori
135         if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) {
136             if (path.equals(WALLPAPER_INFO_FILENAME)) {
137                 outFile = new File(WALLPAPER_INFO);
138                 restoredWallpaper = true;
139             } else if (path.equals(WALLPAPER_IMAGE_FILENAME)) {
140                 outFile = new File(WALLPAPER_IMAGE);
141                 restoredWallpaper = true;
142             }
143         }
144 
145         try {
146             if (outFile == null) {
147                 Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]");
148             }
149             FullBackup.restoreFile(data, size, type, mode, mtime, outFile);
150 
151             if (restoredWallpaper) {
152                 WallpaperManagerService wallpaper =
153                         (WallpaperManagerService)ServiceManager.getService(
154                         Context.WALLPAPER_SERVICE);
155                 wallpaper.settingsRestored();
156             }
157         } catch (IOException e) {
158             if (restoredWallpaper) {
159                 // Make sure we wind up in a good state
160                 (new File(WALLPAPER_IMAGE)).delete();
161                 (new File(WALLPAPER_INFO)).delete();
162             }
163         }
164     }
165 }
166