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.BackupAnnotations.BackupDestination; 22 import android.app.backup.BackupDataInput; 23 import android.app.backup.BackupHelper; 24 import android.app.backup.FullBackup; 25 import android.app.backup.FullBackupDataOutput; 26 import android.app.backup.WallpaperBackupHelper; 27 import android.content.Context; 28 import android.os.Environment; 29 import android.os.ParcelFileDescriptor; 30 import android.os.RemoteException; 31 import android.os.ServiceManager; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.util.Slog; 35 36 import com.google.android.collect.Sets; 37 38 import java.io.File; 39 import java.io.IOException; 40 import java.util.Set; 41 42 /** 43 * Backup agent for various system-managed data. Wallpapers are now handled by a 44 * separate package, but we still process restores from legacy datasets here. 45 */ 46 public class SystemBackupAgent extends BackupAgentHelper { 47 private static final String TAG = "SystemBackupAgent"; 48 49 // Names of the helper tags within the dataset. Changing one of these names will 50 // break the ability to restore from datasets that predate the change. 51 private static final String WALLPAPER_HELPER = "wallpaper"; 52 private static final String SYNC_SETTINGS_HELPER = "account_sync_settings"; 53 private static final String PREFERRED_HELPER = "preferred_activities"; 54 private static final String NOTIFICATION_HELPER = "notifications"; 55 private static final String PERMISSION_HELPER = "permissions"; 56 private static final String USAGE_STATS_HELPER = "usage_stats"; 57 private static final String SHORTCUT_MANAGER_HELPER = "shortcut_manager"; 58 private static final String ACCOUNT_MANAGER_HELPER = "account_manager"; 59 private static final String SLICES_HELPER = "slices"; 60 private static final String PEOPLE_HELPER = "people"; 61 private static final String APP_LOCALES_HELPER = "app_locales"; 62 private static final String APP_GENDER_HELPER = "app_gender"; 63 64 // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME 65 // are also used in the full-backup file format, so must not change unless steps are 66 // taken to support the legacy backed-up datasets. 67 private static final String WALLPAPER_IMAGE_FILENAME = "wallpaper"; 68 private static final String WALLPAPER_INFO_FILENAME = "wallpaper_info.xml"; 69 70 // TODO: Will need to change if backing up non-primary user's wallpaper 71 // TODO: http://b/22388012 72 private static final String WALLPAPER_IMAGE_DIR = 73 Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath(); 74 public static final String WALLPAPER_IMAGE = 75 new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM), 76 "wallpaper").getAbsolutePath(); 77 78 // TODO: Will need to change if backing up non-primary user's wallpaper 79 // TODO: http://b/22388012 80 private static final String WALLPAPER_INFO_DIR = 81 Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath(); 82 public static final String WALLPAPER_INFO = 83 new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM), 84 "wallpaper_info.xml").getAbsolutePath(); 85 // Use old keys to keep legacy data compatibility and avoid writing two wallpapers 86 private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY; 87 88 /** 89 * Helpers that are enabled for "profile" users (such as work profile). See {@link 90 * UserManager#isProfile()}. This is a subset of {@link #sEligibleHelpersForNonSystemUser}. 91 */ 92 private static final Set<String> sEligibleHelpersForProfileUser = 93 Sets.newArraySet( 94 PERMISSION_HELPER, 95 NOTIFICATION_HELPER, 96 SYNC_SETTINGS_HELPER, 97 APP_LOCALES_HELPER); 98 99 /** Helpers that are enabled for full, non-system users. */ 100 private static final Set<String> sEligibleHelpersForNonSystemUser = 101 SetUtils.union(sEligibleHelpersForProfileUser, 102 Sets.newArraySet(ACCOUNT_MANAGER_HELPER, USAGE_STATS_HELPER, PREFERRED_HELPER, 103 SHORTCUT_MANAGER_HELPER)); 104 105 private int mUserId = UserHandle.USER_SYSTEM; 106 private boolean mIsProfileUser = false; 107 108 @Override onCreate(UserHandle user, @BackupDestination int backupDestination)109 public void onCreate(UserHandle user, @BackupDestination int backupDestination) { 110 super.onCreate(user, backupDestination); 111 112 mUserId = user.getIdentifier(); 113 if (mUserId != UserHandle.USER_SYSTEM) { 114 Context context = createContextAsUser(user, /* flags= */ 0); 115 UserManager userManager = context.getSystemService(UserManager.class); 116 mIsProfileUser = userManager.isProfile(); 117 } 118 119 addHelperIfEligibleForUser( 120 SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this, mUserId)); 121 addHelperIfEligibleForUser(PREFERRED_HELPER, new PreferredActivityBackupHelper(mUserId)); 122 addHelperIfEligibleForUser(NOTIFICATION_HELPER, new NotificationBackupHelper(mUserId)); 123 addHelperIfEligibleForUser(PERMISSION_HELPER, new PermissionBackupHelper(mUserId)); 124 addHelperIfEligibleForUser(USAGE_STATS_HELPER, new UsageStatsBackupHelper(mUserId)); 125 addHelperIfEligibleForUser(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper(mUserId)); 126 addHelperIfEligibleForUser(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper(mUserId)); 127 addHelperIfEligibleForUser(SLICES_HELPER, new SliceBackupHelper(this)); 128 addHelperIfEligibleForUser(PEOPLE_HELPER, new PeopleBackupHelper(mUserId)); 129 addHelperIfEligibleForUser(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId)); 130 addHelperIfEligibleForUser(APP_GENDER_HELPER, 131 new AppGrammaticalGenderBackupHelper(mUserId)); 132 } 133 134 @Override onFullBackup(FullBackupDataOutput data)135 public void onFullBackup(FullBackupDataOutput data) throws IOException { 136 // At present we don't back up anything 137 } 138 139 @Override onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)140 public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) 141 throws IOException { 142 // Slot in a restore helper for the older wallpaper backup schema to support restore 143 // from devices still generating data in that format. 144 //TODO(b/147732386): Add multi-display support for wallpaper backup. 145 addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, 146 new String[] { WALLPAPER_IMAGE_KEY})); 147 148 // On restore, we also support a long-ago wallpaper data schema "system_files" 149 addHelper("system_files", new WallpaperBackupHelper(this, 150 new String[] { WALLPAPER_IMAGE_KEY} )); 151 152 super.onRestore(data, appVersionCode, newState); 153 } 154 155 /** 156 * Support for 'adb restore' of legacy archives 157 */ 158 @Override onRestoreFile(ParcelFileDescriptor data, long size, int type, String domain, String path, long mode, long mtime)159 public void onRestoreFile(ParcelFileDescriptor data, long size, 160 int type, String domain, String path, long mode, long mtime) 161 throws IOException { 162 Slog.i(TAG, "Restoring file domain=" + domain + " path=" + path); 163 164 // Bits to indicate postprocessing we may need to perform 165 boolean restoredWallpaper = false; 166 167 File outFile = null; 168 // Various domain+files we understand a priori 169 if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) { 170 if (path.equals(WALLPAPER_INFO_FILENAME)) { 171 outFile = new File(WALLPAPER_INFO); 172 restoredWallpaper = true; 173 } else if (path.equals(WALLPAPER_IMAGE_FILENAME)) { 174 outFile = new File(WALLPAPER_IMAGE); 175 restoredWallpaper = true; 176 } 177 } 178 179 try { 180 if (outFile == null) { 181 Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]"); 182 } 183 FullBackup.restoreFile(data, size, type, mode, mtime, outFile); 184 185 if (restoredWallpaper) { 186 IWallpaperManager wallpaper = 187 (IWallpaperManager)ServiceManager.getService( 188 Context.WALLPAPER_SERVICE); 189 if (wallpaper != null) { 190 try { 191 wallpaper.settingsRestored(); 192 } catch (RemoteException re) { 193 Slog.e(TAG, "Couldn't restore settings\n" + re); 194 } 195 } 196 } 197 } catch (IOException e) { 198 if (restoredWallpaper) { 199 // Make sure we wind up in a good state 200 (new File(WALLPAPER_IMAGE)).delete(); 201 (new File(WALLPAPER_INFO)).delete(); 202 } 203 } 204 } 205 addHelperIfEligibleForUser(String keyPrefix, BackupHelper helper)206 private void addHelperIfEligibleForUser(String keyPrefix, BackupHelper helper) { 207 if (isHelperEligibleForUser(keyPrefix)) { 208 addHelper(keyPrefix, helper); 209 } 210 } 211 isHelperEligibleForUser(String keyPrefix)212 private boolean isHelperEligibleForUser(String keyPrefix) { 213 // All helpers are eligible for the system user. 214 if (mUserId == UserHandle.USER_SYSTEM) { 215 return true; 216 } 217 218 // Profile users (such as work profile) have their own allow list. 219 if (mIsProfileUser) { 220 return sEligibleHelpersForProfileUser.contains(keyPrefix); 221 } 222 223 // Full, non-system users have their own allow list. 224 return sEligibleHelpersForNonSystemUser.contains(keyPrefix); 225 } 226 } 227