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