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