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