1 /* 2 * Copyright (C) 2011 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.commands.bu; 18 19 import android.annotation.UserIdInt; 20 import android.app.backup.IBackupManager; 21 import android.os.ParcelFileDescriptor; 22 import android.os.RemoteException; 23 import android.os.ServiceManager; 24 import android.os.UserHandle; 25 import android.system.OsConstants; 26 import android.util.Log; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 30 import java.io.IOException; 31 import java.util.ArrayList; 32 33 public final class Backup { 34 static final String TAG = "bu"; 35 36 static String[] mArgs; 37 int mNextArg; 38 IBackupManager mBackupManager; 39 40 @VisibleForTesting Backup(IBackupManager backupManager)41 Backup(IBackupManager backupManager) { 42 mBackupManager = backupManager; 43 } 44 Backup()45 Backup() { 46 mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService("backup")); 47 } 48 main(String[] args)49 public static void main(String[] args) { 50 try { 51 new Backup().run(args); 52 } catch (Exception e) { 53 Log.e(TAG, "Error running backup/restore", e); 54 } 55 Log.d(TAG, "Finished."); 56 } 57 run(String[] args)58 public void run(String[] args) { 59 if (mBackupManager == null) { 60 Log.e(TAG, "Can't obtain Backup Manager binder"); 61 return; 62 } 63 64 Log.d(TAG, "Beginning: " + args[0]); 65 mArgs = args; 66 67 int userId = parseUserId(); 68 if (!isBackupActiveForUser(userId)) { 69 Log.e(TAG, "BackupManager is not available for user " + userId); 70 return; 71 } 72 73 String arg = nextArg(); 74 if (arg.equals("backup")) { 75 doBackup(OsConstants.STDOUT_FILENO, userId); 76 } else if (arg.equals("restore")) { 77 doRestore(OsConstants.STDIN_FILENO, userId); 78 } else { 79 showUsage(); 80 } 81 } 82 doBackup(int socketFd, @UserIdInt int userId)83 private void doBackup(int socketFd, @UserIdInt int userId) { 84 ArrayList<String> packages = new ArrayList<String>(); 85 boolean saveApks = false; 86 boolean saveObbs = false; 87 boolean saveShared = false; 88 boolean doEverything = false; 89 boolean doWidgets = false; 90 boolean allIncludesSystem = true; 91 boolean doCompress = true; 92 boolean doKeyValue = false; 93 94 String arg; 95 while ((arg = nextArg()) != null) { 96 if (arg.startsWith("-")) { 97 if ("-apk".equals(arg)) { 98 saveApks = true; 99 } else if ("-noapk".equals(arg)) { 100 saveApks = false; 101 } else if ("-obb".equals(arg)) { 102 saveObbs = true; 103 } else if ("-noobb".equals(arg)) { 104 saveObbs = false; 105 } else if ("-shared".equals(arg)) { 106 saveShared = true; 107 } else if ("-noshared".equals(arg)) { 108 saveShared = false; 109 } else if ("-system".equals(arg)) { 110 allIncludesSystem = true; 111 } else if ("-nosystem".equals(arg)) { 112 allIncludesSystem = false; 113 } else if ("-widgets".equals(arg)) { 114 doWidgets = true; 115 } else if ("-nowidgets".equals(arg)) { 116 doWidgets = false; 117 } else if ("-all".equals(arg)) { 118 doEverything = true; 119 } else if ("-compress".equals(arg)) { 120 doCompress = true; 121 } else if ("-nocompress".equals(arg)) { 122 doCompress = false; 123 } else if ("-keyvalue".equals(arg)) { 124 doKeyValue = true; 125 } else if ("-nokeyvalue".equals(arg)) { 126 doKeyValue = false; 127 } else if ("-user".equals(arg)) { 128 // User ID has been processed in run(), ignore the next argument. 129 nextArg(); 130 continue; 131 } else { 132 Log.w(TAG, "Unknown backup flag " + arg); 133 continue; 134 } 135 } else { 136 // Not a flag; treat as a package name 137 packages.add(arg); 138 } 139 } 140 141 if (doEverything && packages.size() > 0) { 142 Log.w(TAG, "-all passed for backup along with specific package names"); 143 } 144 145 if (!doEverything && !saveShared && packages.size() == 0) { 146 Log.e(TAG, "no backup packages supplied and neither -shared nor -all given"); 147 return; 148 } 149 150 ParcelFileDescriptor fd = null; 151 try { 152 fd = ParcelFileDescriptor.adoptFd(socketFd); 153 String[] packArray = new String[packages.size()]; 154 mBackupManager.adbBackup(userId, fd, saveApks, saveObbs, saveShared, doWidgets, doEverything, 155 allIncludesSystem, doCompress, doKeyValue, packages.toArray(packArray)); 156 } catch (RemoteException e) { 157 Log.e(TAG, "Unable to invoke backup manager for backup"); 158 } finally { 159 if (fd != null) { 160 try { 161 fd.close(); 162 } catch (IOException e) { 163 Log.e(TAG, "IO error closing output for backup: " + e.getMessage()); 164 } 165 } 166 } 167 } 168 doRestore(int socketFd, @UserIdInt int userId)169 private void doRestore(int socketFd, @UserIdInt int userId) { 170 // No arguments to restore 171 ParcelFileDescriptor fd = null; 172 try { 173 fd = ParcelFileDescriptor.adoptFd(socketFd); 174 mBackupManager.adbRestore(userId, fd); 175 } catch (RemoteException e) { 176 Log.e(TAG, "Unable to invoke backup manager for restore"); 177 } finally { 178 if (fd != null) { 179 try { 180 fd.close(); 181 } catch (IOException e) {} 182 } 183 } 184 } 185 parseUserId()186 private @UserIdInt int parseUserId() { 187 for (int argNumber = 0; argNumber < mArgs.length - 1; argNumber++) { 188 if ("-user".equals(mArgs[argNumber])) { 189 return UserHandle.parseUserArg(mArgs[argNumber + 1]); 190 } 191 } 192 193 return UserHandle.USER_SYSTEM; 194 } 195 isBackupActiveForUser(int userId)196 private boolean isBackupActiveForUser(int userId) { 197 try { 198 return mBackupManager.isBackupServiceActive(userId); 199 } catch (RemoteException e) { 200 Log.e(TAG, "Could not access BackupManager: " + e.toString()); 201 return false; 202 } 203 } 204 showUsage()205 private static void showUsage() { 206 System.err.println(" backup [-user USER_ID] [-f FILE] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared]"); 207 System.err.println(" [-all] [-system|-nosystem] [-keyvalue|-nokeyvalue] [PACKAGE...]"); 208 System.err.println(" write an archive of the device's data to FILE [default=backup.adb]"); 209 System.err.println(" package list optional if -all/-shared are supplied"); 210 System.err.println(" -user: user ID for which to perform the operation (default - system user)"); 211 System.err.println(" -apk/-noapk: do/don't back up .apk files (default -noapk)"); 212 System.err.println(" -obb/-noobb: do/don't back up .obb files (default -noobb)"); 213 System.err.println(" -shared|-noshared: do/don't back up shared storage (default -noshared)"); 214 System.err.println(" -all: back up all installed applications"); 215 System.err.println(" -system|-nosystem: include system apps in -all (default -system)"); 216 System.err.println(" -keyvalue|-nokeyvalue: include apps that perform key/value backups."); 217 System.err.println(" (default -nokeyvalue)"); 218 System.err.println(" restore [-user USER_ID] FILE restore device contents from FILE"); 219 System.err.println(" -user: user ID for which to perform the operation (default - system user)"); 220 } 221 nextArg()222 private String nextArg() { 223 if (mNextArg >= mArgs.length) { 224 return null; 225 } 226 String arg = mArgs[mNextArg]; 227 mNextArg++; 228 return arg; 229 } 230 }