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