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.backup; 18 19 import android.app.IWallpaperManager; 20 import android.app.backup.BackupAgentHelper; 21 import android.app.backup.BackupDataInput; 22 import android.app.backup.BackupHelper; 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.RemoteException; 30 import android.os.ServiceManager; 31 import android.os.UserHandle; 32 import android.util.Slog; 33 34 import com.google.android.collect.Sets; 35 36 import java.io.File; 37 import java.io.IOException; 38 import java.util.Set; 39 40 /** 41 * Backup agent for various system-managed data. Wallpapers are now handled by a 42 * separate package, but we still process restores from legacy datasets here. 43 */ 44 public class SystemBackupAgent extends BackupAgentHelper { 45 private static final String TAG = "SystemBackupAgent"; 46 47 // Names of the helper tags within the dataset. Changing one of these names will 48 // break the ability to restore from datasets that predate the change. 49 private static final String WALLPAPER_HELPER = "wallpaper"; 50 private static final String SYNC_SETTINGS_HELPER = "account_sync_settings"; 51 private static final String PREFERRED_HELPER = "preferred_activities"; 52 private static final String NOTIFICATION_HELPER = "notifications"; 53 private static final String PERMISSION_HELPER = "permissions"; 54 private static final String USAGE_STATS_HELPER = "usage_stats"; 55 private static final String SHORTCUT_MANAGER_HELPER = "shortcut_manager"; 56 private static final String ACCOUNT_MANAGER_HELPER = "account_manager"; 57 private static final String SLICES_HELPER = "slices"; 58 59 // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME 60 // are also used in the full-backup file format, so must not change unless steps are 61 // taken to support the legacy backed-up datasets. 62 private static final String WALLPAPER_IMAGE_FILENAME = "wallpaper"; 63 private static final String WALLPAPER_INFO_FILENAME = "wallpaper_info.xml"; 64 65 // TODO: Will need to change if backing up non-primary user's wallpaper 66 // TODO: http://b/22388012 67 private static final String WALLPAPER_IMAGE_DIR = 68 Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath(); 69 public static final String WALLPAPER_IMAGE = 70 new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM), 71 "wallpaper").getAbsolutePath(); 72 73 // TODO: Will need to change if backing up non-primary user's wallpaper 74 // TODO: http://b/22388012 75 private static final String WALLPAPER_INFO_DIR = 76 Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath(); 77 public static final String WALLPAPER_INFO = 78 new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM), 79 "wallpaper_info.xml").getAbsolutePath(); 80 // Use old keys to keep legacy data compatibility and avoid writing two wallpapers 81 private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY; 82 83 private static final Set<String> sEligibleForMultiUser = Sets.newArraySet( 84 PERMISSION_HELPER, NOTIFICATION_HELPER, SYNC_SETTINGS_HELPER); 85 86 private int mUserId = UserHandle.USER_SYSTEM; 87 88 @Override onCreate(UserHandle user)89 public void onCreate(UserHandle user) { 90 super.onCreate(user); 91 92 mUserId = user.getIdentifier(); 93 94 addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this, mUserId)); 95 addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); 96 addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(mUserId)); 97 addHelper(PERMISSION_HELPER, new PermissionBackupHelper(mUserId)); 98 addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); 99 addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); 100 addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); 101 addHelper(SLICES_HELPER, new SliceBackupHelper(this)); 102 } 103 104 @Override onFullBackup(FullBackupDataOutput data)105 public void onFullBackup(FullBackupDataOutput data) throws IOException { 106 // At present we don't back up anything 107 } 108 109 @Override onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)110 public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) 111 throws IOException { 112 // Slot in a restore helper for the older wallpaper backup schema to support restore 113 // from devices still generating data in that format. 114 addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, 115 new String[] { WALLPAPER_IMAGE_KEY})); 116 117 // On restore, we also support a long-ago wallpaper data schema "system_files" 118 addHelper("system_files", new WallpaperBackupHelper(this, 119 new String[] { WALLPAPER_IMAGE_KEY} )); 120 121 super.onRestore(data, appVersionCode, newState); 122 } 123 124 @Override addHelper(String keyPrefix, BackupHelper helper)125 public void addHelper(String keyPrefix, BackupHelper helper) { 126 if (mUserId != UserHandle.USER_SYSTEM && !sEligibleForMultiUser.contains(keyPrefix)) { 127 return; 128 } 129 130 super.addHelper(keyPrefix, helper); 131 } 132 133 /** 134 * Support for 'adb restore' of legacy archives 135 */ 136 @Override onRestoreFile(ParcelFileDescriptor data, long size, int type, String domain, String path, long mode, long mtime)137 public void onRestoreFile(ParcelFileDescriptor data, long size, 138 int type, String domain, String path, long mode, long mtime) 139 throws IOException { 140 Slog.i(TAG, "Restoring file domain=" + domain + " path=" + path); 141 142 // Bits to indicate postprocessing we may need to perform 143 boolean restoredWallpaper = false; 144 145 File outFile = null; 146 // Various domain+files we understand a priori 147 if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) { 148 if (path.equals(WALLPAPER_INFO_FILENAME)) { 149 outFile = new File(WALLPAPER_INFO); 150 restoredWallpaper = true; 151 } else if (path.equals(WALLPAPER_IMAGE_FILENAME)) { 152 outFile = new File(WALLPAPER_IMAGE); 153 restoredWallpaper = true; 154 } 155 } 156 157 try { 158 if (outFile == null) { 159 Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]"); 160 } 161 FullBackup.restoreFile(data, size, type, mode, mtime, outFile); 162 163 if (restoredWallpaper) { 164 IWallpaperManager wallpaper = 165 (IWallpaperManager)ServiceManager.getService( 166 Context.WALLPAPER_SERVICE); 167 if (wallpaper != null) { 168 try { 169 wallpaper.settingsRestored(); 170 } catch (RemoteException re) { 171 Slog.e(TAG, "Couldn't restore settings\n" + re); 172 } 173 } 174 } 175 } catch (IOException e) { 176 if (restoredWallpaper) { 177 // Make sure we wind up in a good state 178 (new File(WALLPAPER_IMAGE)).delete(); 179 (new File(WALLPAPER_INFO)).delete(); 180 } 181 } 182 } 183 } 184