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