1 /* 2 * Copyright (C) 2014 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.backup.BackupManager; 20 import android.app.backup.IBackupManager; 21 import android.app.backup.IBackupObserver; 22 import android.app.backup.IBackupManagerMonitor; 23 import android.app.backup.IFullBackupRestoreObserver; 24 import android.app.backup.IRestoreSession; 25 import android.app.backup.ISelectBackupTransportCallback; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.os.Binder; 30 import android.os.Environment; 31 import android.os.IBinder; 32 import android.os.ParcelFileDescriptor; 33 import android.os.Process; 34 import android.os.RemoteException; 35 import android.os.SystemProperties; 36 import android.os.UserHandle; 37 import android.util.Slog; 38 39 import com.android.internal.util.DumpUtils; 40 41 import java.io.File; 42 import java.io.FileDescriptor; 43 import java.io.IOException; 44 import java.io.PrintWriter; 45 46 public class Trampoline extends IBackupManager.Stub { 47 static final String TAG = "BackupManagerService"; 48 static final boolean DEBUG_TRAMPOLINE = false; 49 50 // When this file is present, the backup service is inactive 51 static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress"; 52 53 // Product-level suppression of backup/restore 54 static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable"; 55 56 final Context mContext; 57 final File mSuppressFile; // existence testing & creating synchronized on 'this' 58 final boolean mGlobalDisable; 59 volatile BackupManagerService mService; 60 Trampoline(Context context)61 public Trampoline(Context context) { 62 mContext = context; 63 File dir = new File(Environment.getDataDirectory(), "backup"); 64 dir.mkdirs(); 65 mSuppressFile = new File(dir, BACKUP_SUPPRESS_FILENAME); 66 mGlobalDisable = SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false); 67 } 68 69 // internal control API initialize(final int whichUser)70 public void initialize(final int whichUser) { 71 // Note that only the owner user is currently involved in backup/restore 72 // TODO: http://b/22388012 73 if (whichUser == UserHandle.USER_SYSTEM) { 74 // Does this product support backup/restore at all? 75 if (mGlobalDisable) { 76 Slog.i(TAG, "Backup/restore not supported"); 77 return; 78 } 79 80 synchronized (this) { 81 if (!mSuppressFile.exists()) { 82 mService = new BackupManagerService(mContext, this); 83 } else { 84 Slog.i(TAG, "Backup inactive in user " + whichUser); 85 } 86 } 87 } 88 } 89 setBackupServiceActive(final int userHandle, boolean makeActive)90 public void setBackupServiceActive(final int userHandle, boolean makeActive) { 91 // Only the DPM should be changing the active state of backup 92 final int caller = Binder.getCallingUid(); 93 if (caller != Process.SYSTEM_UID 94 && caller != Process.ROOT_UID) { 95 throw new SecurityException("No permission to configure backup activity"); 96 } 97 98 if (mGlobalDisable) { 99 Slog.i(TAG, "Backup/restore not supported"); 100 return; 101 } 102 // TODO: http://b/22388012 103 if (userHandle == UserHandle.USER_SYSTEM) { 104 synchronized (this) { 105 if (makeActive != isBackupServiceActive(userHandle)) { 106 Slog.i(TAG, "Making backup " 107 + (makeActive ? "" : "in") + "active in user " + userHandle); 108 if (makeActive) { 109 mService = new BackupManagerService(mContext, this); 110 mSuppressFile.delete(); 111 } else { 112 mService = null; 113 try { 114 mSuppressFile.createNewFile(); 115 } catch (IOException e) { 116 Slog.e(TAG, "Unable to persist backup service inactivity"); 117 } 118 } 119 } 120 } 121 } 122 } 123 124 /** 125 * Querying activity state of backup service. Calling this method before initialize yields 126 * undefined result. 127 * @param userHandle The user in which the activity state of backup service is queried. 128 * @return true if the service is active. 129 */ isBackupServiceActive(final int userHandle)130 public boolean isBackupServiceActive(final int userHandle) { 131 // TODO: http://b/22388012 132 if (userHandle == UserHandle.USER_SYSTEM) { 133 synchronized (this) { 134 return mService != null; 135 } 136 } 137 return false; 138 } 139 140 // IBackupManager binder API 141 @Override dataChanged(String packageName)142 public void dataChanged(String packageName) throws RemoteException { 143 BackupManagerService svc = mService; 144 if (svc != null) { 145 svc.dataChanged(packageName); 146 } 147 } 148 149 @Override clearBackupData(String transportName, String packageName)150 public void clearBackupData(String transportName, String packageName) 151 throws RemoteException { 152 BackupManagerService svc = mService; 153 if (svc != null) { 154 svc.clearBackupData(transportName, packageName); 155 } 156 } 157 158 @Override agentConnected(String packageName, IBinder agent)159 public void agentConnected(String packageName, IBinder agent) throws RemoteException { 160 BackupManagerService svc = mService; 161 if (svc != null) { 162 svc.agentConnected(packageName, agent); 163 } 164 } 165 166 @Override agentDisconnected(String packageName)167 public void agentDisconnected(String packageName) throws RemoteException { 168 BackupManagerService svc = mService; 169 if (svc != null) { 170 svc.agentDisconnected(packageName); 171 } 172 } 173 174 @Override restoreAtInstall(String packageName, int token)175 public void restoreAtInstall(String packageName, int token) throws RemoteException { 176 BackupManagerService svc = mService; 177 if (svc != null) { 178 svc.restoreAtInstall(packageName, token); 179 } 180 } 181 182 @Override setBackupEnabled(boolean isEnabled)183 public void setBackupEnabled(boolean isEnabled) throws RemoteException { 184 BackupManagerService svc = mService; 185 if (svc != null) { 186 svc.setBackupEnabled(isEnabled); 187 } 188 } 189 190 @Override setAutoRestore(boolean doAutoRestore)191 public void setAutoRestore(boolean doAutoRestore) throws RemoteException { 192 BackupManagerService svc = mService; 193 if (svc != null) { 194 svc.setAutoRestore(doAutoRestore); 195 } 196 } 197 198 @Override setBackupProvisioned(boolean isProvisioned)199 public void setBackupProvisioned(boolean isProvisioned) throws RemoteException { 200 BackupManagerService svc = mService; 201 if (svc != null) { 202 svc.setBackupProvisioned(isProvisioned); 203 } 204 } 205 206 @Override isBackupEnabled()207 public boolean isBackupEnabled() throws RemoteException { 208 BackupManagerService svc = mService; 209 return (svc != null) ? svc.isBackupEnabled() : false; 210 } 211 212 @Override setBackupPassword(String currentPw, String newPw)213 public boolean setBackupPassword(String currentPw, String newPw) throws RemoteException { 214 BackupManagerService svc = mService; 215 return (svc != null) ? svc.setBackupPassword(currentPw, newPw) : false; 216 } 217 218 @Override hasBackupPassword()219 public boolean hasBackupPassword() throws RemoteException { 220 BackupManagerService svc = mService; 221 return (svc != null) ? svc.hasBackupPassword() : false; 222 } 223 224 @Override backupNow()225 public void backupNow() throws RemoteException { 226 BackupManagerService svc = mService; 227 if (svc != null) { 228 svc.backupNow(); 229 } 230 } 231 232 @Override adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, boolean allApps, boolean allIncludesSystem, boolean doCompress, boolean doKeyValue, String[] packageNames)233 public void adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, 234 boolean includeShared, boolean doWidgets, boolean allApps, 235 boolean allIncludesSystem, boolean doCompress, boolean doKeyValue, String[] packageNames) 236 throws RemoteException { 237 BackupManagerService svc = mService; 238 if (svc != null) { 239 svc.adbBackup(fd, includeApks, includeObbs, includeShared, doWidgets, 240 allApps, allIncludesSystem, doCompress, doKeyValue, packageNames); 241 } 242 } 243 244 @Override fullTransportBackup(String[] packageNames)245 public void fullTransportBackup(String[] packageNames) throws RemoteException { 246 BackupManagerService svc = mService; 247 if (svc != null) { 248 svc.fullTransportBackup(packageNames); 249 } 250 } 251 252 @Override adbRestore(ParcelFileDescriptor fd)253 public void adbRestore(ParcelFileDescriptor fd) throws RemoteException { 254 BackupManagerService svc = mService; 255 if (svc != null) { 256 svc.adbRestore(fd); 257 } 258 } 259 260 @Override acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword, String encryptionPassword, IFullBackupRestoreObserver observer)261 public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword, 262 String encryptionPassword, IFullBackupRestoreObserver observer) 263 throws RemoteException { 264 BackupManagerService svc = mService; 265 if (svc != null) { 266 svc.acknowledgeAdbBackupOrRestore(token, allow, 267 curPassword, encryptionPassword, observer); 268 } 269 } 270 271 @Override getCurrentTransport()272 public String getCurrentTransport() throws RemoteException { 273 BackupManagerService svc = mService; 274 return (svc != null) ? svc.getCurrentTransport() : null; 275 } 276 277 @Override listAllTransports()278 public String[] listAllTransports() throws RemoteException { 279 BackupManagerService svc = mService; 280 return (svc != null) ? svc.listAllTransports() : null; 281 } 282 283 @Override listAllTransportComponents()284 public ComponentName[] listAllTransportComponents() throws RemoteException { 285 BackupManagerService svc = mService; 286 return (svc != null) ? svc.listAllTransportComponents() : null; 287 } 288 289 @Override getTransportWhitelist()290 public String[] getTransportWhitelist() { 291 BackupManagerService svc = mService; 292 return (svc != null) ? svc.getTransportWhitelist() : null; 293 } 294 295 @Override selectBackupTransport(String transport)296 public String selectBackupTransport(String transport) throws RemoteException { 297 BackupManagerService svc = mService; 298 return (svc != null) ? svc.selectBackupTransport(transport) : null; 299 } 300 301 @Override selectBackupTransportAsync(ComponentName transport, ISelectBackupTransportCallback listener)302 public void selectBackupTransportAsync(ComponentName transport, 303 ISelectBackupTransportCallback listener) throws RemoteException { 304 BackupManagerService svc = mService; 305 if (svc != null) { 306 svc.selectBackupTransportAsync(transport, listener); 307 } else { 308 if (listener != null) { 309 try { 310 listener.onFailure(BackupManager.ERROR_BACKUP_NOT_ALLOWED); 311 } catch (RemoteException ex) { 312 // Ignore 313 } 314 } 315 } 316 } 317 318 @Override getConfigurationIntent(String transport)319 public Intent getConfigurationIntent(String transport) throws RemoteException { 320 BackupManagerService svc = mService; 321 return (svc != null) ? svc.getConfigurationIntent(transport) : null; 322 } 323 324 @Override getDestinationString(String transport)325 public String getDestinationString(String transport) throws RemoteException { 326 BackupManagerService svc = mService; 327 return (svc != null) ? svc.getDestinationString(transport) : null; 328 } 329 330 @Override getDataManagementIntent(String transport)331 public Intent getDataManagementIntent(String transport) throws RemoteException { 332 BackupManagerService svc = mService; 333 return (svc != null) ? svc.getDataManagementIntent(transport) : null; 334 } 335 336 @Override getDataManagementLabel(String transport)337 public String getDataManagementLabel(String transport) throws RemoteException { 338 BackupManagerService svc = mService; 339 return (svc != null) ? svc.getDataManagementLabel(transport) : null; 340 } 341 342 @Override beginRestoreSession(String packageName, String transportID)343 public IRestoreSession beginRestoreSession(String packageName, String transportID) 344 throws RemoteException { 345 BackupManagerService svc = mService; 346 return (svc != null) ? svc.beginRestoreSession(packageName, transportID) : null; 347 } 348 349 @Override opComplete(int token, long result)350 public void opComplete(int token, long result) throws RemoteException { 351 BackupManagerService svc = mService; 352 if (svc != null) { 353 svc.opComplete(token, result); 354 } 355 } 356 357 @Override getAvailableRestoreToken(String packageName)358 public long getAvailableRestoreToken(String packageName) { 359 BackupManagerService svc = mService; 360 return (svc != null) ? svc.getAvailableRestoreToken(packageName) : 0; 361 } 362 363 @Override isAppEligibleForBackup(String packageName)364 public boolean isAppEligibleForBackup(String packageName) { 365 BackupManagerService svc = mService; 366 return (svc != null) ? svc.isAppEligibleForBackup(packageName) : false; 367 } 368 369 @Override requestBackup(String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, int flags)370 public int requestBackup(String[] packages, IBackupObserver observer, 371 IBackupManagerMonitor monitor, int flags) throws RemoteException { 372 BackupManagerService svc = mService; 373 if (svc == null) { 374 return BackupManager.ERROR_BACKUP_NOT_ALLOWED; 375 } 376 return svc.requestBackup(packages, observer, monitor, flags); 377 } 378 379 @Override cancelBackups()380 public void cancelBackups() throws RemoteException { 381 BackupManagerService svc = mService; 382 if (svc != null) { 383 svc.cancelBackups(); 384 } 385 } 386 387 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)388 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 389 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 390 391 BackupManagerService svc = mService; 392 if (svc != null) { 393 svc.dump(fd, pw, args); 394 } else { 395 pw.println("Inactive"); 396 } 397 } 398 399 // Full backup/restore entry points - non-Binder; called directly 400 // by the full-backup scheduled job beginFullBackup(FullBackupJob scheduledJob)401 /* package */ boolean beginFullBackup(FullBackupJob scheduledJob) { 402 BackupManagerService svc = mService; 403 return (svc != null) ? svc.beginFullBackup(scheduledJob) : false; 404 } 405 endFullBackup()406 /* package */ void endFullBackup() { 407 BackupManagerService svc = mService; 408 if (svc != null) { 409 svc.endFullBackup(); 410 } 411 } 412 } 413