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