SystemBackupAgent.java revision e9fd1fa31ad6f62d1eb6f32cdcdab50349f246eb
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 private static final String PERMISSION_HELPER = "permissions"; 50 51 // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME 52 // are also used in the full-backup file format, so must not change unless steps are 53 // taken to support the legacy backed-up datasets. 54 private static final String WALLPAPER_IMAGE_FILENAME = "wallpaper"; 55 private static final String WALLPAPER_INFO_FILENAME = "wallpaper_info.xml"; 56 57 // TODO: Will need to change if backing up non-primary user's wallpaper 58 // TODO: http://b/22388012 59 private static final String WALLPAPER_IMAGE_DIR = 60 Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath(); 61 private static final String WALLPAPER_IMAGE = WallpaperBackupHelper.WALLPAPER_IMAGE; 62 63 // TODO: Will need to change if backing up non-primary user's wallpaper 64 // TODO: http://b/22388012 65 private static final String WALLPAPER_INFO_DIR = 66 Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).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(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this)); 96 addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); 97 addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); 98 addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); 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(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this)); 131 addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); 132 addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); 133 addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); 134 135 try { 136 super.onRestore(data, appVersionCode, newState); 137 138 IWallpaperManager wallpaper = (IWallpaperManager) ServiceManager.getService( 139 Context.WALLPAPER_SERVICE); 140 if (wallpaper != null) { 141 try { 142 wallpaper.settingsRestored(); 143 } catch (RemoteException re) { 144 Slog.e(TAG, "Couldn't restore settings\n" + re); 145 } 146 } 147 } catch (IOException ex) { 148 // If there was a failure, delete everything for the wallpaper, this is too aggressive, 149 // but this is hopefully a rare failure. 150 Slog.d(TAG, "restore failed", ex); 151 (new File(WALLPAPER_IMAGE)).delete(); 152 (new File(WALLPAPER_INFO)).delete(); 153 } 154 } 155 156 @Override 157 public void onRestoreFile(ParcelFileDescriptor data, long size, 158 int type, String domain, String path, long mode, long mtime) 159 throws IOException { 160 Slog.i(TAG, "Restoring file domain=" + domain + " path=" + path); 161 162 // Bits to indicate postprocessing we may need to perform 163 boolean restoredWallpaper = false; 164 165 File outFile = null; 166 // Various domain+files we understand a priori 167 if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) { 168 if (path.equals(WALLPAPER_INFO_FILENAME)) { 169 outFile = new File(WALLPAPER_INFO); 170 restoredWallpaper = true; 171 } else if (path.equals(WALLPAPER_IMAGE_FILENAME)) { 172 outFile = new File(WALLPAPER_IMAGE); 173 restoredWallpaper = true; 174 } 175 } 176 177 try { 178 if (outFile == null) { 179 Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]"); 180 } 181 FullBackup.restoreFile(data, size, type, mode, mtime, outFile); 182 183 if (restoredWallpaper) { 184 IWallpaperManager wallpaper = 185 (IWallpaperManager)ServiceManager.getService( 186 Context.WALLPAPER_SERVICE); 187 if (wallpaper != null) { 188 try { 189 wallpaper.settingsRestored(); 190 } catch (RemoteException re) { 191 Slog.e(TAG, "Couldn't restore settings\n" + re); 192 } 193 } 194 } 195 } catch (IOException e) { 196 if (restoredWallpaper) { 197 // Make sure we wind up in a good state 198 (new File(WALLPAPER_IMAGE)).delete(); 199 (new File(WALLPAPER_INFO)).delete(); 200 } 201 } 202 } 203} 204