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