1 /* 2 * Copyright (C) 2010 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 android.app.backup; 18 19 import android.app.WallpaperManager; 20 import android.content.Context; 21 import android.graphics.BitmapFactory; 22 import android.graphics.Point; 23 import android.os.Environment; 24 import android.os.ParcelFileDescriptor; 25 import android.os.UserHandle; 26 import android.util.Slog; 27 import android.view.Display; 28 import android.view.WindowManager; 29 30 import java.io.File; 31 32 /** 33 * Helper for backing up / restoring wallpapers. Basically an AbsoluteFileBackupHelper, 34 * but with logic for deciding what to do with restored wallpaper images. 35 * 36 * @hide 37 */ 38 public class WallpaperBackupHelper extends FileBackupHelperBase implements BackupHelper { 39 private static final String TAG = "WallpaperBackupHelper"; 40 private static final boolean DEBUG = false; 41 42 // This path must match what the WallpaperManagerService uses 43 // TODO: Will need to change if backing up non-primary user's wallpaper 44 public static final String WALLPAPER_IMAGE = 45 new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER), 46 "wallpaper").getAbsolutePath(); 47 public static final String WALLPAPER_INFO = 48 new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER), 49 "wallpaper_info.xml").getAbsolutePath(); 50 // Use old keys to keep legacy data compatibility and avoid writing two wallpapers 51 public static final String WALLPAPER_IMAGE_KEY = 52 "/data/data/com.android.settings/files/wallpaper"; 53 public static final String WALLPAPER_INFO_KEY = "/data/system/wallpaper_info.xml"; 54 55 // Stage file - should be adjacent to the WALLPAPER_IMAGE location. The wallpapers 56 // will be saved to this file from the restore stream, then renamed to the proper 57 // location if it's deemed suitable. 58 // TODO: Will need to change if backing up non-primary user's wallpaper 59 private static final String STAGE_FILE = 60 new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER), 61 "wallpaper-tmp").getAbsolutePath(); 62 63 Context mContext; 64 String[] mFiles; 65 String[] mKeys; 66 double mDesiredMinWidth; 67 double mDesiredMinHeight; 68 69 /** 70 * Construct a helper for backing up / restoring the files at the given absolute locations 71 * within the file system. 72 * 73 * @param context 74 * @param files 75 */ 76 public WallpaperBackupHelper(Context context, String[] files, String[] keys) { 77 super(context); 78 79 mContext = context; 80 mFiles = files; 81 mKeys = keys; 82 83 WallpaperManager wpm; 84 wpm = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE); 85 mDesiredMinWidth = (double) wpm.getDesiredMinimumWidth(); 86 mDesiredMinHeight = (double) wpm.getDesiredMinimumHeight(); 87 88 if (mDesiredMinWidth <= 0 || mDesiredMinHeight <= 0) { 89 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 90 Display d = wm.getDefaultDisplay(); 91 Point size = new Point(); 92 d.getSize(size); 93 mDesiredMinWidth = size.x; 94 mDesiredMinHeight = size.y; 95 } 96 97 if (DEBUG) { 98 Slog.d(TAG, "dmW=" + mDesiredMinWidth + " dmH=" + mDesiredMinHeight); 99 } 100 } 101 102 /** 103 * Based on oldState, determine which of the files from the application's data directory 104 * need to be backed up, write them to the data stream, and fill in newState with the 105 * state as it exists now. 106 */ 107 public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, 108 ParcelFileDescriptor newState) { 109 performBackup_checked(oldState, data, newState, mFiles, mKeys); 110 } 111 112 /** 113 * Restore one absolute file entity from the restore stream. If we're restoring the 114 * magic wallpaper file, take specific action to determine whether it is suitable for 115 * the current device. 116 */ 117 public void restoreEntity(BackupDataInputStream data) { 118 final String key = data.getKey(); 119 if (isKeyInList(key, mKeys)) { 120 if (key.equals(WALLPAPER_IMAGE_KEY)) { 121 // restore the file to the stage for inspection 122 File f = new File(STAGE_FILE); 123 if (writeFile(f, data)) { 124 125 // Preflight the restored image's dimensions without loading it 126 BitmapFactory.Options options = new BitmapFactory.Options(); 127 options.inJustDecodeBounds = true; 128 BitmapFactory.decodeFile(STAGE_FILE, options); 129 130 if (DEBUG) Slog.d(TAG, "Restoring wallpaper image w=" + options.outWidth 131 + " h=" + options.outHeight); 132 133 // How much does the image differ from our preference? The threshold 134 // here is set to accept any image larger than our target, because 135 // scaling down is acceptable; but to reject images that are deemed 136 // "too small" to scale up attractively. The value 1.33 is just barely 137 // too low to pass Nexus 1 or Droid wallpapers for use on a Xoom, but 138 // will pass anything relatively larger. 139 double widthRatio = mDesiredMinWidth / options.outWidth; 140 double heightRatio = mDesiredMinHeight / options.outHeight; 141 if (widthRatio > 0 && widthRatio < 1.33 142 && heightRatio > 0 && heightRatio < 1.33) { 143 // sufficiently close to our resolution; go ahead and use it 144 if (DEBUG) Slog.d(TAG, "wallpaper dimension match; using"); 145 f.renameTo(new File(WALLPAPER_IMAGE)); 146 // TODO: spin a service to copy the restored image to sd/usb storage, 147 // since it does not exist anywhere other than the private wallpaper 148 // file. 149 } else { 150 if (DEBUG) Slog.d(TAG, "dimensions too far off: wr=" + widthRatio 151 + " hr=" + heightRatio); 152 f.delete(); 153 } 154 } 155 } else if (key.equals(WALLPAPER_INFO_KEY)) { 156 // XML file containing wallpaper info 157 File f = new File(WALLPAPER_INFO); 158 writeFile(f, data); 159 } 160 } 161 } 162 } 163