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