• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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