1/* 2 * Copyright (C) 2017 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 17package com.android.server.backup; 18 19import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND; 20import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT; 21import static com.android.server.backup.internal.BackupHandler.MSG_FULL_CONFIRMATION_TIMEOUT; 22import static com.android.server.backup.internal.BackupHandler.MSG_OP_COMPLETE; 23import static com.android.server.backup.internal.BackupHandler.MSG_REQUEST_BACKUP; 24import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT; 25import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT; 26import static com.android.server.backup.internal.BackupHandler.MSG_RETRY_CLEAR; 27import static com.android.server.backup.internal.BackupHandler.MSG_RETRY_INIT; 28import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_BACKUP; 29import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_RESTORE; 30import static com.android.server.backup.internal.BackupHandler.MSG_RUN_BACKUP; 31import static com.android.server.backup.internal.BackupHandler.MSG_RUN_CLEAR; 32import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE; 33import static com.android.server.backup.internal.BackupHandler.MSG_SCHEDULE_BACKUP_PACKAGE; 34 35import android.annotation.Nullable; 36import android.app.ActivityManager; 37import android.app.AlarmManager; 38import android.app.AppGlobals; 39import android.app.IActivityManager; 40import android.app.IBackupAgent; 41import android.app.PendingIntent; 42import android.app.backup.BackupManager; 43import android.app.backup.BackupManagerMonitor; 44import android.app.backup.FullBackup; 45import android.app.backup.IBackupManager; 46import android.app.backup.IBackupManagerMonitor; 47import android.app.backup.IBackupObserver; 48import android.app.backup.IFullBackupRestoreObserver; 49import android.app.backup.IRestoreSession; 50import android.app.backup.ISelectBackupTransportCallback; 51import android.app.backup.SelectBackupTransportCallback; 52import android.content.ActivityNotFoundException; 53import android.content.BroadcastReceiver; 54import android.content.ComponentName; 55import android.content.ContentResolver; 56import android.content.Context; 57import android.content.Intent; 58import android.content.IntentFilter; 59import android.content.pm.ApplicationInfo; 60import android.content.pm.IPackageManager; 61import android.content.pm.PackageInfo; 62import android.content.pm.PackageManager; 63import android.content.pm.PackageManager.NameNotFoundException; 64import android.database.ContentObserver; 65import android.net.Uri; 66import android.os.Binder; 67import android.os.Bundle; 68import android.os.Environment; 69import android.os.HandlerThread; 70import android.os.IBinder; 71import android.os.Message; 72import android.os.ParcelFileDescriptor; 73import android.os.PowerManager; 74import android.os.PowerSaveState; 75import android.os.Process; 76import android.os.RemoteException; 77import android.os.SELinux; 78import android.os.ServiceManager; 79import android.os.SystemClock; 80import android.os.UserHandle; 81import android.os.storage.IStorageManager; 82import android.os.storage.StorageManager; 83import android.provider.Settings; 84import android.text.TextUtils; 85import android.util.ArraySet; 86import android.util.AtomicFile; 87import android.util.EventLog; 88import android.util.Pair; 89import android.util.Slog; 90import android.util.SparseArray; 91 92import com.android.internal.annotations.GuardedBy; 93import com.android.internal.backup.IBackupTransport; 94import com.android.internal.util.DumpUtils; 95import com.android.server.AppWidgetBackupBridge; 96import com.android.server.EventLogTags; 97import com.android.server.SystemConfig; 98import com.android.server.SystemService; 99import com.android.server.backup.fullbackup.FullBackupEntry; 100import com.android.server.backup.fullbackup.PerformFullTransportBackupTask; 101import com.android.server.backup.internal.BackupHandler; 102import com.android.server.backup.internal.BackupRequest; 103import com.android.server.backup.internal.ClearDataObserver; 104import com.android.server.backup.internal.Operation; 105import com.android.server.backup.internal.PerformInitializeTask; 106import com.android.server.backup.internal.ProvisionedObserver; 107import com.android.server.backup.internal.RunBackupReceiver; 108import com.android.server.backup.internal.RunInitializeReceiver; 109import com.android.server.backup.params.AdbBackupParams; 110import com.android.server.backup.params.AdbParams; 111import com.android.server.backup.params.AdbRestoreParams; 112import com.android.server.backup.params.BackupParams; 113import com.android.server.backup.params.ClearParams; 114import com.android.server.backup.params.ClearRetryParams; 115import com.android.server.backup.params.RestoreParams; 116import com.android.server.backup.restore.ActiveRestoreSession; 117import com.android.server.backup.restore.PerformUnifiedRestoreTask; 118import com.android.server.backup.utils.AppBackupUtils; 119import com.android.server.backup.utils.BackupManagerMonitorUtils; 120import com.android.server.backup.utils.BackupObserverUtils; 121import com.android.server.backup.utils.SparseArrayUtils; 122import com.android.server.power.BatterySaverPolicy.ServiceType; 123 124import com.google.android.collect.Sets; 125 126import java.io.BufferedInputStream; 127import java.io.ByteArrayOutputStream; 128import java.io.DataInputStream; 129import java.io.DataOutputStream; 130import java.io.EOFException; 131import java.io.File; 132import java.io.FileDescriptor; 133import java.io.FileInputStream; 134import java.io.FileNotFoundException; 135import java.io.FileOutputStream; 136import java.io.IOException; 137import java.io.InputStream; 138import java.io.PrintWriter; 139import java.io.RandomAccessFile; 140import java.security.SecureRandom; 141import java.text.SimpleDateFormat; 142import java.util.ArrayDeque; 143import java.util.ArrayList; 144import java.util.Arrays; 145import java.util.Collections; 146import java.util.Date; 147import java.util.HashMap; 148import java.util.HashSet; 149import java.util.List; 150import java.util.Queue; 151import java.util.Random; 152import java.util.Set; 153import java.util.concurrent.CountDownLatch; 154 155public class RefactoredBackupManagerService implements BackupManagerServiceInterface { 156 157 public static final String TAG = "BackupManagerService"; 158 public static final boolean DEBUG = true; 159 public static final boolean MORE_DEBUG = false; 160 public static final boolean DEBUG_SCHEDULING = MORE_DEBUG || true; 161 162 // File containing backup-enabled state. Contains a single byte; 163 // nonzero == enabled. File missing or contains a zero byte == disabled. 164 private static final String BACKUP_ENABLE_FILE = "backup_enabled"; 165 166 // System-private key used for backing up an app's widget state. Must 167 // begin with U+FFxx by convention (we reserve all keys starting 168 // with U+FF00 or higher for system use). 169 public static final String KEY_WIDGET_STATE = "\uffed\uffedwidget"; 170 171 // Name and current contents version of the full-backup manifest file 172 // 173 // Manifest version history: 174 // 175 // 1 : initial release 176 public static final String BACKUP_MANIFEST_FILENAME = "_manifest"; 177 public static final int BACKUP_MANIFEST_VERSION = 1; 178 179 // External archive format version history: 180 // 181 // 1 : initial release 182 // 2 : no format change per se; version bump to facilitate PBKDF2 version skew detection 183 // 3 : introduced "_meta" metadata file; no other format change per se 184 // 4 : added support for new device-encrypted storage locations 185 // 5 : added support for key-value packages 186 public static final int BACKUP_FILE_VERSION = 5; 187 public static final String BACKUP_FILE_HEADER_MAGIC = "ANDROID BACKUP\n"; 188 public static final String BACKUP_METADATA_FILENAME = "_meta"; 189 public static final int BACKUP_METADATA_VERSION = 1; 190 public static final int BACKUP_WIDGET_METADATA_TOKEN = 0x01FFED01; 191 192 private static final boolean COMPRESS_FULL_BACKUPS = true; // should be true in production 193 194 public static final String SETTINGS_PACKAGE = "com.android.providers.settings"; 195 public static final String SHARED_BACKUP_AGENT_PACKAGE = "com.android.sharedstoragebackup"; 196 private static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST"; 197 198 // Retry interval for clear/init when the transport is unavailable 199 private static final long TRANSPORT_RETRY_INTERVAL = 1 * AlarmManager.INTERVAL_HOUR; 200 201 public static final String RUN_BACKUP_ACTION = "android.app.backup.intent.RUN"; 202 public static final String RUN_INITIALIZE_ACTION = "android.app.backup.intent.INIT"; 203 204 // Timeout interval for deciding that a bind or clear-data has taken too long 205 private static final long TIMEOUT_INTERVAL = 10 * 1000; 206 207 // Timeout intervals for agent backup & restore operations 208 public static final long TIMEOUT_BACKUP_INTERVAL = 30 * 1000; 209 public static final long TIMEOUT_FULL_BACKUP_INTERVAL = 5 * 60 * 1000; 210 public static final long TIMEOUT_SHARED_BACKUP_INTERVAL = 30 * 60 * 1000; 211 public static final long TIMEOUT_RESTORE_INTERVAL = 60 * 1000; 212 public static final long TIMEOUT_RESTORE_FINISHED_INTERVAL = 30 * 1000; 213 214 // User confirmation timeout for a full backup/restore operation. It's this long in 215 // order to give them time to enter the backup password. 216 private static final long TIMEOUT_FULL_CONFIRMATION = 60 * 1000; 217 218 // How long between attempts to perform a full-data backup of any given app 219 private static final long MIN_FULL_BACKUP_INTERVAL = 1000 * 60 * 60 * 24; // one day 220 221 // If an app is busy when we want to do a full-data backup, how long to defer the retry. 222 // This is fuzzed, so there are two parameters; backoff_min + Rand[0, backoff_fuzz) 223 private static final long BUSY_BACKOFF_MIN_MILLIS = 1000 * 60 * 60; // one hour 224 private static final int BUSY_BACKOFF_FUZZ = 1000 * 60 * 60 * 2; // two hours 225 226 private Context mContext; 227 private PackageManager mPackageManager; 228 private IPackageManager mPackageManagerBinder; 229 private IActivityManager mActivityManager; 230 private PowerManager mPowerManager; 231 private AlarmManager mAlarmManager; 232 private IStorageManager mStorageManager; 233 234 private IBackupManager mBackupManagerBinder; 235 236 private final TransportManager mTransportManager; 237 238 private boolean mEnabled; // access to this is synchronized on 'this' 239 private boolean mProvisioned; 240 private boolean mAutoRestore; 241 private PowerManager.WakeLock mWakelock; 242 private HandlerThread mHandlerThread; 243 private BackupHandler mBackupHandler; 244 private PendingIntent mRunBackupIntent; 245 private PendingIntent mRunInitIntent; 246 private BroadcastReceiver mRunBackupReceiver; 247 private BroadcastReceiver mRunInitReceiver; 248 // map UIDs to the set of participating packages under that UID 249 private final SparseArray<HashSet<String>> mBackupParticipants 250 = new SparseArray<>(); 251 252 // Backups that we haven't started yet. Keys are package names. 253 private HashMap<String, BackupRequest> mPendingBackups 254 = new HashMap<>(); 255 256 // Pseudoname that we use for the Package Manager metadata "package" 257 public static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; 258 259 // locking around the pending-backup management 260 private final Object mQueueLock = new Object(); 261 262 // The thread performing the sequence of queued backups binds to each app's agent 263 // in succession. Bind notifications are asynchronously delivered through the 264 // Activity Manager; use this lock object to signal when a requested binding has 265 // completed. 266 private final Object mAgentConnectLock = new Object(); 267 private IBackupAgent mConnectedAgent; 268 private volatile boolean mBackupRunning; 269 private volatile boolean mConnecting; 270 private volatile long mLastBackupPass; 271 272 // For debugging, we maintain a progress trace of operations during backup 273 public static final boolean DEBUG_BACKUP_TRACE = true; 274 private final List<String> mBackupTrace = new ArrayList<>(); 275 276 // A similar synchronization mechanism around clearing apps' data for restore 277 private final Object mClearDataLock = new Object(); 278 private volatile boolean mClearingData; 279 280 private final BackupPasswordManager mBackupPasswordManager; 281 282 @GuardedBy("mPendingRestores") 283 private boolean mIsRestoreInProgress; 284 @GuardedBy("mPendingRestores") 285 private final Queue<PerformUnifiedRestoreTask> mPendingRestores = new ArrayDeque<>(); 286 287 private ActiveRestoreSession mActiveRestoreSession; 288 289 // Watch the device provisioning operation during setup 290 private ContentObserver mProvisionedObserver; 291 292 // The published binder is actually to a singleton trampoline object that calls 293 // through to the proper code. This indirection lets us turn down the heavy 294 // implementation object on the fly without disturbing binders that have been 295 // cached elsewhere in the system. 296 static Trampoline sInstance; 297 298 static Trampoline getInstance() { 299 // Always constructed during system bringup, so no need to lazy-init 300 return sInstance; 301 } 302 303 public Context getContext() { 304 return mContext; 305 } 306 307 public void setContext(Context context) { 308 mContext = context; 309 } 310 311 public PackageManager getPackageManager() { 312 return mPackageManager; 313 } 314 315 public void setPackageManager(PackageManager packageManager) { 316 mPackageManager = packageManager; 317 } 318 319 public IPackageManager getPackageManagerBinder() { 320 return mPackageManagerBinder; 321 } 322 323 public void setPackageManagerBinder(IPackageManager packageManagerBinder) { 324 mPackageManagerBinder = packageManagerBinder; 325 } 326 327 public IActivityManager getActivityManager() { 328 return mActivityManager; 329 } 330 331 public void setActivityManager(IActivityManager activityManager) { 332 mActivityManager = activityManager; 333 } 334 335 public AlarmManager getAlarmManager() { 336 return mAlarmManager; 337 } 338 339 public void setAlarmManager(AlarmManager alarmManager) { 340 mAlarmManager = alarmManager; 341 } 342 343 public void setBackupManagerBinder(IBackupManager backupManagerBinder) { 344 mBackupManagerBinder = backupManagerBinder; 345 } 346 347 public TransportManager getTransportManager() { 348 return mTransportManager; 349 } 350 351 public boolean isEnabled() { 352 return mEnabled; 353 } 354 355 public void setEnabled(boolean enabled) { 356 mEnabled = enabled; 357 } 358 359 public boolean isProvisioned() { 360 return mProvisioned; 361 } 362 363 public void setProvisioned(boolean provisioned) { 364 mProvisioned = provisioned; 365 } 366 367 public PowerManager.WakeLock getWakelock() { 368 return mWakelock; 369 } 370 371 public void setWakelock(PowerManager.WakeLock wakelock) { 372 mWakelock = wakelock; 373 } 374 375 public BackupHandler getBackupHandler() { 376 return mBackupHandler; 377 } 378 379 public void setBackupHandler(BackupHandler backupHandler) { 380 mBackupHandler = backupHandler; 381 } 382 383 public PendingIntent getRunInitIntent() { 384 return mRunInitIntent; 385 } 386 387 public void setRunInitIntent(PendingIntent runInitIntent) { 388 mRunInitIntent = runInitIntent; 389 } 390 391 public HashMap<String, BackupRequest> getPendingBackups() { 392 return mPendingBackups; 393 } 394 395 public void setPendingBackups( 396 HashMap<String, BackupRequest> pendingBackups) { 397 mPendingBackups = pendingBackups; 398 } 399 400 public Object getQueueLock() { 401 return mQueueLock; 402 } 403 404 public boolean isBackupRunning() { 405 return mBackupRunning; 406 } 407 408 public void setBackupRunning(boolean backupRunning) { 409 mBackupRunning = backupRunning; 410 } 411 412 public long getLastBackupPass() { 413 return mLastBackupPass; 414 } 415 416 public void setLastBackupPass(long lastBackupPass) { 417 mLastBackupPass = lastBackupPass; 418 } 419 420 public Object getClearDataLock() { 421 return mClearDataLock; 422 } 423 424 public boolean isClearingData() { 425 return mClearingData; 426 } 427 428 public void setClearingData(boolean clearingData) { 429 mClearingData = clearingData; 430 } 431 432 public boolean isRestoreInProgress() { 433 return mIsRestoreInProgress; 434 } 435 436 public void setRestoreInProgress(boolean restoreInProgress) { 437 mIsRestoreInProgress = restoreInProgress; 438 } 439 440 public Queue<PerformUnifiedRestoreTask> getPendingRestores() { 441 return mPendingRestores; 442 } 443 444 public ActiveRestoreSession getActiveRestoreSession() { 445 return mActiveRestoreSession; 446 } 447 448 public void setActiveRestoreSession( 449 ActiveRestoreSession activeRestoreSession) { 450 mActiveRestoreSession = activeRestoreSession; 451 } 452 453 public SparseArray<Operation> getCurrentOperations() { 454 return mCurrentOperations; 455 } 456 457 public Object getCurrentOpLock() { 458 return mCurrentOpLock; 459 } 460 461 public SparseArray<AdbParams> getAdbBackupRestoreConfirmations() { 462 return mAdbBackupRestoreConfirmations; 463 } 464 465 public File getBaseStateDir() { 466 return mBaseStateDir; 467 } 468 469 public void setBaseStateDir(File baseStateDir) { 470 mBaseStateDir = baseStateDir; 471 } 472 473 public File getDataDir() { 474 return mDataDir; 475 } 476 477 public void setDataDir(File dataDir) { 478 mDataDir = dataDir; 479 } 480 481 public DataChangedJournal getJournal() { 482 return mJournal; 483 } 484 485 public void setJournal(@Nullable DataChangedJournal journal) { 486 mJournal = journal; 487 } 488 489 public SecureRandom getRng() { 490 return mRng; 491 } 492 493 public Set<String> getAncestralPackages() { 494 return mAncestralPackages; 495 } 496 497 public void setAncestralPackages(Set<String> ancestralPackages) { 498 mAncestralPackages = ancestralPackages; 499 } 500 501 public long getAncestralToken() { 502 return mAncestralToken; 503 } 504 505 public void setAncestralToken(long ancestralToken) { 506 mAncestralToken = ancestralToken; 507 } 508 509 public long getCurrentToken() { 510 return mCurrentToken; 511 } 512 513 public void setCurrentToken(long currentToken) { 514 mCurrentToken = currentToken; 515 } 516 517 public ArraySet<String> getPendingInits() { 518 return mPendingInits; 519 } 520 521 public void clearPendingInits() { 522 mPendingInits.clear(); 523 } 524 525 public PerformFullTransportBackupTask getRunningFullBackupTask() { 526 return mRunningFullBackupTask; 527 } 528 529 public void setRunningFullBackupTask( 530 PerformFullTransportBackupTask runningFullBackupTask) { 531 mRunningFullBackupTask = runningFullBackupTask; 532 } 533 534 public static final class Lifecycle extends SystemService { 535 536 public Lifecycle(Context context) { 537 super(context); 538 sInstance = new Trampoline(context); 539 } 540 541 @Override 542 public void onStart() { 543 publishBinderService(Context.BACKUP_SERVICE, sInstance); 544 } 545 546 @Override 547 public void onUnlockUser(int userId) { 548 if (userId == UserHandle.USER_SYSTEM) { 549 sInstance.initialize(userId); 550 551 // Migrate legacy setting 552 if (!backupSettingMigrated(userId)) { 553 if (DEBUG) { 554 Slog.i(TAG, "Backup enable apparently not migrated"); 555 } 556 final ContentResolver r = sInstance.mContext.getContentResolver(); 557 final int enableState = Settings.Secure.getIntForUser(r, 558 Settings.Secure.BACKUP_ENABLED, -1, userId); 559 if (enableState >= 0) { 560 if (DEBUG) { 561 Slog.i(TAG, "Migrating enable state " + (enableState != 0)); 562 } 563 writeBackupEnableState(enableState != 0, userId); 564 Settings.Secure.putStringForUser(r, 565 Settings.Secure.BACKUP_ENABLED, null, userId); 566 } else { 567 if (DEBUG) { 568 Slog.i(TAG, "Backup not yet configured; retaining null enable state"); 569 } 570 } 571 } 572 573 try { 574 sInstance.setBackupEnabled(readBackupEnableState(userId)); 575 } catch (RemoteException e) { 576 // can't happen; it's a local object 577 } 578 } 579 } 580 } 581 582 // Bookkeeping of in-flight operations for timeout etc. purposes. The operation 583 // token is the index of the entry in the pending-operations list. 584 public static final int OP_PENDING = 0; 585 private static final int OP_ACKNOWLEDGED = 1; 586 private static final int OP_TIMEOUT = -1; 587 588 // Waiting for backup agent to respond during backup operation. 589 public static final int OP_TYPE_BACKUP_WAIT = 0; 590 591 // Waiting for backup agent to respond during restore operation. 592 public static final int OP_TYPE_RESTORE_WAIT = 1; 593 594 // An entire backup operation spanning multiple packages. 595 public static final int OP_TYPE_BACKUP = 2; 596 597 /** 598 * mCurrentOperations contains the list of currently active operations. 599 * 600 * If type of operation is OP_TYPE_WAIT, it are waiting for an ack or timeout. 601 * An operation wraps a BackupRestoreTask within it. 602 * It's the responsibility of this task to remove the operation from this array. 603 * 604 * A BackupRestore task gets notified of ack/timeout for the operation via 605 * BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called 606 * on the mCurrentOpLock. 607 * {@link RefactoredBackupManagerService#waitUntilOperationComplete(int)} is 608 * used in various places to 'wait' for notifyAll and detect change of pending state of an 609 * operation. So typically, an operation will be removed from this array by: 610 * - BackupRestoreTask#handleCancel and 611 * - BackupRestoreTask#operationComplete OR waitUntilOperationComplete. Do not remove at both 612 * these places because waitUntilOperationComplete relies on the operation being present to 613 * determine its completion status. 614 * 615 * If type of operation is OP_BACKUP, it is a task running backups. It provides a handle to 616 * cancel backup tasks. 617 */ 618 @GuardedBy("mCurrentOpLock") 619 private final SparseArray<Operation> mCurrentOperations = new SparseArray<>(); 620 private final Object mCurrentOpLock = new Object(); 621 private final Random mTokenGenerator = new Random(); 622 623 private final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<>(); 624 625 // Where we keep our journal files and other bookkeeping 626 private File mBaseStateDir; 627 private File mDataDir; 628 private File mJournalDir; 629 @Nullable private DataChangedJournal mJournal; 630 631 private final SecureRandom mRng = new SecureRandom(); 632 633 // Keep a log of all the apps we've ever backed up, and what the 634 // dataset tokens are for both the current backup dataset and 635 // the ancestral dataset. 636 private File mEverStored; 637 private HashSet<String> mEverStoredApps = new HashSet<>(); 638 639 private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1; 640 // increment when the schema changes 641 private File mTokenFile; 642 private Set<String> mAncestralPackages = null; 643 private long mAncestralToken = 0; 644 private long mCurrentToken = 0; 645 646 // Persistently track the need to do a full init 647 private static final String INIT_SENTINEL_FILE_NAME = "_need_init_"; 648 private ArraySet<String> mPendingInits = new ArraySet<>(); // transport names 649 650 // Round-robin queue for scheduling full backup passes 651 private static final int SCHEDULE_FILE_VERSION = 1; // current version of the schedule file 652 653 private File mFullBackupScheduleFile; 654 // If we're running a schedule-driven full backup, this is the task instance doing it 655 656 @GuardedBy("mQueueLock") 657 private PerformFullTransportBackupTask mRunningFullBackupTask; 658 659 @GuardedBy("mQueueLock") 660 private ArrayList<FullBackupEntry> mFullBackupQueue; 661 662 // Utility: build a new random integer token 663 @Override 664 public int generateRandomIntegerToken() { 665 int token; 666 do { 667 synchronized (mTokenGenerator) { 668 token = mTokenGenerator.nextInt(); 669 } 670 } while (token < 0); 671 return token; 672 } 673 674 // ----- Debug-only backup operation trace ----- 675 public void addBackupTrace(String s) { 676 if (DEBUG_BACKUP_TRACE) { 677 synchronized (mBackupTrace) { 678 mBackupTrace.add(s); 679 } 680 } 681 } 682 683 public void clearBackupTrace() { 684 if (DEBUG_BACKUP_TRACE) { 685 synchronized (mBackupTrace) { 686 mBackupTrace.clear(); 687 } 688 } 689 } 690 691 // ----- Main service implementation ----- 692 693 public RefactoredBackupManagerService(Context context, Trampoline parent) { 694 mContext = context; 695 mPackageManager = context.getPackageManager(); 696 mPackageManagerBinder = AppGlobals.getPackageManager(); 697 mActivityManager = ActivityManager.getService(); 698 699 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 700 mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 701 mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount")); 702 703 mBackupManagerBinder = Trampoline.asInterface(parent.asBinder()); 704 705 // spin up the backup/restore handler thread 706 mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND); 707 mHandlerThread.start(); 708 mBackupHandler = new BackupHandler(this, mHandlerThread.getLooper()); 709 710 // Set up our bookkeeping 711 final ContentResolver resolver = context.getContentResolver(); 712 mProvisioned = Settings.Global.getInt(resolver, 713 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 714 mAutoRestore = Settings.Secure.getInt(resolver, 715 Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0; 716 717 mProvisionedObserver = new ProvisionedObserver(this, mBackupHandler); 718 resolver.registerContentObserver( 719 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), 720 false, mProvisionedObserver); 721 722 // If Encrypted file systems is enabled or disabled, this call will return the 723 // correct directory. 724 mBaseStateDir = new File(Environment.getDataDirectory(), "backup"); 725 mBaseStateDir.mkdirs(); 726 if (!SELinux.restorecon(mBaseStateDir)) { 727 Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir); 728 } 729 730 // This dir on /cache is managed directly in init.rc 731 mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage"); 732 733 mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng); 734 735 // Alarm receivers for scheduled backups & initialization operations 736 mRunBackupReceiver = new RunBackupReceiver(this); 737 IntentFilter filter = new IntentFilter(); 738 filter.addAction(RUN_BACKUP_ACTION); 739 context.registerReceiver(mRunBackupReceiver, filter, 740 android.Manifest.permission.BACKUP, null); 741 742 mRunInitReceiver = new RunInitializeReceiver(this); 743 filter = new IntentFilter(); 744 filter.addAction(RUN_INITIALIZE_ACTION); 745 context.registerReceiver(mRunInitReceiver, filter, 746 android.Manifest.permission.BACKUP, null); 747 748 Intent backupIntent = new Intent(RUN_BACKUP_ACTION); 749 backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 750 mRunBackupIntent = PendingIntent.getBroadcast(context, 0, backupIntent, 0); 751 752 Intent initIntent = new Intent(RUN_INITIALIZE_ACTION); 753 initIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 754 mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0); 755 756 // Set up the backup-request journaling 757 mJournalDir = new File(mBaseStateDir, "pending"); 758 mJournalDir.mkdirs(); // creates mBaseStateDir along the way 759 mJournal = null; // will be created on first use 760 761 // Set up the various sorts of package tracking we do 762 mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule"); 763 initPackageTracking(); 764 765 // Build our mapping of uid to backup client services. This implicitly 766 // schedules a backup pass on the Package Manager metadata the first 767 // time anything needs to be backed up. 768 synchronized (mBackupParticipants) { 769 addPackageParticipantsLocked(null); 770 } 771 772 // Set up our transport options and initialize the default transport 773 // TODO: Don't create transports that we don't need to? 774 SystemConfig systemConfig = SystemConfig.getInstance(); 775 Set<ComponentName> transportWhitelist = systemConfig.getBackupTransportWhitelist(); 776 777 String transport = Settings.Secure.getString(context.getContentResolver(), 778 Settings.Secure.BACKUP_TRANSPORT); 779 if (TextUtils.isEmpty(transport)) { 780 transport = null; 781 } 782 String currentTransport = transport; 783 if (DEBUG) Slog.v(TAG, "Starting with transport " + currentTransport); 784 785 mTransportManager = new TransportManager(context, transportWhitelist, currentTransport, 786 mTransportBoundListener, mHandlerThread.getLooper()); 787 mTransportManager.registerAllTransports(); 788 789 // Now that we know about valid backup participants, parse any 790 // leftover journal files into the pending backup set 791 mBackupHandler.post(() -> parseLeftoverJournals()); 792 793 // Power management 794 mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*"); 795 } 796 797 private void initPackageTracking() { 798 if (MORE_DEBUG) Slog.v(TAG, "` tracking"); 799 800 // Remember our ancestral dataset 801 mTokenFile = new File(mBaseStateDir, "ancestral"); 802 try (RandomAccessFile tf = new RandomAccessFile(mTokenFile, "r")) { 803 int version = tf.readInt(); 804 if (version == CURRENT_ANCESTRAL_RECORD_VERSION) { 805 mAncestralToken = tf.readLong(); 806 mCurrentToken = tf.readLong(); 807 808 int numPackages = tf.readInt(); 809 if (numPackages >= 0) { 810 mAncestralPackages = new HashSet<>(); 811 for (int i = 0; i < numPackages; i++) { 812 String pkgName = tf.readUTF(); 813 mAncestralPackages.add(pkgName); 814 } 815 } 816 } 817 } catch (FileNotFoundException fnf) { 818 // Probably innocuous 819 Slog.v(TAG, "No ancestral data"); 820 } catch (IOException e) { 821 Slog.w(TAG, "Unable to read token file", e); 822 } 823 824 // Keep a log of what apps we've ever backed up. Because we might have 825 // rebooted in the middle of an operation that was removing something from 826 // this log, we sanity-check its contents here and reconstruct it. 827 mEverStored = new File(mBaseStateDir, "processed"); 828 File tempProcessedFile = new File(mBaseStateDir, "processed.new"); 829 830 // If we were in the middle of removing something from the ever-backed-up 831 // file, there might be a transient "processed.new" file still present. 832 // Ignore it -- we'll validate "processed" against the current package set. 833 if (tempProcessedFile.exists()) { 834 tempProcessedFile.delete(); 835 } 836 837 // If there are previous contents, parse them out then start a new 838 // file to continue the recordkeeping. 839 if (mEverStored.exists()) { 840 try (RandomAccessFile temp = new RandomAccessFile(tempProcessedFile, "rws"); 841 RandomAccessFile in = new RandomAccessFile(mEverStored, "r")) { 842 // Loop until we hit EOF 843 while (true) { 844 String pkg = in.readUTF(); 845 try { 846 // is this package still present? 847 mPackageManager.getPackageInfo(pkg, 0); 848 // if we get here then yes it is; remember it 849 mEverStoredApps.add(pkg); 850 temp.writeUTF(pkg); 851 if (MORE_DEBUG) Slog.v(TAG, " + " + pkg); 852 } catch (NameNotFoundException e) { 853 // nope, this package was uninstalled; don't include it 854 if (MORE_DEBUG) Slog.v(TAG, " - " + pkg); 855 } 856 } 857 } catch (EOFException e) { 858 // Once we've rewritten the backup history log, atomically replace the 859 // old one with the new one then reopen the file for continuing use. 860 if (!tempProcessedFile.renameTo(mEverStored)) { 861 Slog.e(TAG, "Error renaming " + tempProcessedFile + " to " + mEverStored); 862 } 863 } catch (IOException e) { 864 Slog.e(TAG, "Error in processed file", e); 865 } 866 } 867 868 synchronized (mQueueLock) { 869 // Resume the full-data backup queue 870 mFullBackupQueue = readFullBackupSchedule(); 871 } 872 873 // Register for broadcasts about package install, etc., so we can 874 // update the provider list. 875 IntentFilter filter = new IntentFilter(); 876 filter.addAction(Intent.ACTION_PACKAGE_ADDED); 877 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 878 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 879 filter.addDataScheme("package"); 880 mContext.registerReceiver(mBroadcastReceiver, filter); 881 // Register for events related to sdcard installation. 882 IntentFilter sdFilter = new IntentFilter(); 883 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 884 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 885 mContext.registerReceiver(mBroadcastReceiver, sdFilter); 886 } 887 888 private ArrayList<FullBackupEntry> readFullBackupSchedule() { 889 boolean changed = false; 890 ArrayList<FullBackupEntry> schedule = null; 891 List<PackageInfo> apps = 892 PackageManagerBackupAgent.getStorableApplications(mPackageManager); 893 894 if (mFullBackupScheduleFile.exists()) { 895 try (FileInputStream fstream = new FileInputStream(mFullBackupScheduleFile); 896 BufferedInputStream bufStream = new BufferedInputStream(fstream); 897 DataInputStream in = new DataInputStream(bufStream)) { 898 int version = in.readInt(); 899 if (version != SCHEDULE_FILE_VERSION) { 900 Slog.e(TAG, "Unknown backup schedule version " + version); 901 return null; 902 } 903 904 final int N = in.readInt(); 905 schedule = new ArrayList<>(N); 906 907 // HashSet instead of ArraySet specifically because we want the eventual 908 // lookups against O(hundreds) of entries to be as fast as possible, and 909 // we discard the set immediately after the scan so the extra memory 910 // overhead is transient. 911 HashSet<String> foundApps = new HashSet<>(N); 912 913 for (int i = 0; i < N; i++) { 914 String pkgName = in.readUTF(); 915 long lastBackup = in.readLong(); 916 foundApps.add(pkgName); // all apps that we've addressed already 917 try { 918 PackageInfo pkg = mPackageManager.getPackageInfo(pkgName, 0); 919 if (AppBackupUtils.appGetsFullBackup(pkg) 920 && AppBackupUtils.appIsEligibleForBackup( 921 pkg.applicationInfo)) { 922 schedule.add(new FullBackupEntry(pkgName, lastBackup)); 923 } else { 924 if (DEBUG) { 925 Slog.i(TAG, "Package " + pkgName 926 + " no longer eligible for full backup"); 927 } 928 } 929 } catch (NameNotFoundException e) { 930 if (DEBUG) { 931 Slog.i(TAG, "Package " + pkgName 932 + " not installed; dropping from full backup"); 933 } 934 } 935 } 936 937 // New apps can arrive "out of band" via OTA and similar, so we also need to 938 // scan to make sure that we're tracking all full-backup candidates properly 939 for (PackageInfo app : apps) { 940 if (AppBackupUtils.appGetsFullBackup(app) 941 && AppBackupUtils.appIsEligibleForBackup( 942 app.applicationInfo)) { 943 if (!foundApps.contains(app.packageName)) { 944 if (MORE_DEBUG) { 945 Slog.i(TAG, "New full backup app " + app.packageName + " found"); 946 } 947 schedule.add(new FullBackupEntry(app.packageName, 0)); 948 changed = true; 949 } 950 } 951 } 952 953 Collections.sort(schedule); 954 } catch (Exception e) { 955 Slog.e(TAG, "Unable to read backup schedule", e); 956 mFullBackupScheduleFile.delete(); 957 schedule = null; 958 } 959 } 960 961 if (schedule == null) { 962 // no prior queue record, or unable to read it. Set up the queue 963 // from scratch. 964 changed = true; 965 schedule = new ArrayList<>(apps.size()); 966 for (PackageInfo info : apps) { 967 if (AppBackupUtils.appGetsFullBackup(info) && AppBackupUtils.appIsEligibleForBackup( 968 info.applicationInfo)) { 969 schedule.add(new FullBackupEntry(info.packageName, 0)); 970 } 971 } 972 } 973 974 if (changed) { 975 writeFullBackupScheduleAsync(); 976 } 977 return schedule; 978 } 979 980 private Runnable mFullBackupScheduleWriter = new Runnable() { 981 @Override 982 public void run() { 983 synchronized (mQueueLock) { 984 try { 985 ByteArrayOutputStream bufStream = new ByteArrayOutputStream(4096); 986 DataOutputStream bufOut = new DataOutputStream(bufStream); 987 bufOut.writeInt(SCHEDULE_FILE_VERSION); 988 989 // version 1: 990 // 991 // [int] # of packages in the queue = N 992 // N * { 993 // [utf8] package name 994 // [long] last backup time for this package 995 // } 996 int N = mFullBackupQueue.size(); 997 bufOut.writeInt(N); 998 999 for (int i = 0; i < N; i++) { 1000 FullBackupEntry entry = mFullBackupQueue.get(i); 1001 bufOut.writeUTF(entry.packageName); 1002 bufOut.writeLong(entry.lastBackup); 1003 } 1004 bufOut.flush(); 1005 1006 AtomicFile af = new AtomicFile(mFullBackupScheduleFile); 1007 FileOutputStream out = af.startWrite(); 1008 out.write(bufStream.toByteArray()); 1009 af.finishWrite(out); 1010 } catch (Exception e) { 1011 Slog.e(TAG, "Unable to write backup schedule!", e); 1012 } 1013 } 1014 } 1015 }; 1016 1017 private void writeFullBackupScheduleAsync() { 1018 mBackupHandler.removeCallbacks(mFullBackupScheduleWriter); 1019 mBackupHandler.post(mFullBackupScheduleWriter); 1020 } 1021 1022 private void parseLeftoverJournals() { 1023 ArrayList<DataChangedJournal> journals = DataChangedJournal.listJournals(mJournalDir); 1024 for (DataChangedJournal journal : journals) { 1025 if (!journal.equals(mJournal)) { 1026 try { 1027 journal.forEach(packageName -> { 1028 Slog.i(TAG, "Found stale backup journal, scheduling"); 1029 if (MORE_DEBUG) Slog.i(TAG, " " + packageName); 1030 dataChangedImpl(packageName); 1031 }); 1032 } catch (IOException e) { 1033 Slog.e(TAG, "Can't read " + journal, e); 1034 } 1035 } 1036 } 1037 } 1038 1039 // Used for generating random salts or passwords 1040 public byte[] randomBytes(int bits) { 1041 byte[] array = new byte[bits / 8]; 1042 mRng.nextBytes(array); 1043 return array; 1044 } 1045 1046 @Override 1047 public boolean setBackupPassword(String currentPw, String newPw) { 1048 return mBackupPasswordManager.setBackupPassword(currentPw, newPw); 1049 } 1050 1051 @Override 1052 public boolean hasBackupPassword() { 1053 return mBackupPasswordManager.hasBackupPassword(); 1054 } 1055 1056 public boolean backupPasswordMatches(String currentPw) { 1057 return mBackupPasswordManager.backupPasswordMatches(currentPw); 1058 } 1059 1060 // Maintain persistent state around whether need to do an initialize operation. 1061 // Must be called with the queue lock held. 1062 public void recordInitPendingLocked(boolean isPending, String transportName) { 1063 if (MORE_DEBUG) { 1064 Slog.i(TAG, "recordInitPendingLocked: " + isPending 1065 + " on transport " + transportName); 1066 } 1067 mBackupHandler.removeMessages(MSG_RETRY_INIT); 1068 1069 try { 1070 IBackupTransport transport = mTransportManager.getTransportBinder(transportName); 1071 if (transport != null) { 1072 String transportDirName = transport.transportDirName(); 1073 File stateDir = new File(mBaseStateDir, transportDirName); 1074 File initPendingFile = new File(stateDir, INIT_SENTINEL_FILE_NAME); 1075 1076 if (isPending) { 1077 // We need an init before we can proceed with sending backup data. 1078 // Record that with an entry in our set of pending inits, as well as 1079 // journaling it via creation of a sentinel file. 1080 mPendingInits.add(transportName); 1081 try { 1082 (new FileOutputStream(initPendingFile)).close(); 1083 } catch (IOException ioe) { 1084 // Something is badly wrong with our permissions; just try to move on 1085 } 1086 } else { 1087 // No more initialization needed; wipe the journal and reset our state. 1088 initPendingFile.delete(); 1089 mPendingInits.remove(transportName); 1090 } 1091 return; // done; don't fall through to the error case 1092 } 1093 } catch (Exception e) { 1094 // transport threw when asked its name; fall through to the lookup-failed case 1095 Slog.e(TAG, "Transport " + transportName + " failed to report name: " 1096 + e.getMessage()); 1097 } 1098 1099 // The named transport doesn't exist or threw. This operation is 1100 // important, so we record the need for a an init and post a message 1101 // to retry the init later. 1102 if (isPending) { 1103 mPendingInits.add(transportName); 1104 mBackupHandler.sendMessageDelayed( 1105 mBackupHandler.obtainMessage(MSG_RETRY_INIT, 1106 (isPending ? 1 : 0), 1107 0, 1108 transportName), 1109 TRANSPORT_RETRY_INTERVAL); 1110 } 1111 } 1112 1113 // Reset all of our bookkeeping, in response to having been told that 1114 // the backend data has been wiped [due to idle expiry, for example], 1115 // so we must re-upload all saved settings. 1116 public void resetBackupState(File stateFileDir) { 1117 synchronized (mQueueLock) { 1118 // Wipe the "what we've ever backed up" tracking 1119 mEverStoredApps.clear(); 1120 mEverStored.delete(); 1121 1122 mCurrentToken = 0; 1123 writeRestoreTokens(); 1124 1125 // Remove all the state files 1126 for (File sf : stateFileDir.listFiles()) { 1127 // ... but don't touch the needs-init sentinel 1128 if (!sf.getName().equals(INIT_SENTINEL_FILE_NAME)) { 1129 sf.delete(); 1130 } 1131 } 1132 } 1133 1134 // Enqueue a new backup of every participant 1135 synchronized (mBackupParticipants) { 1136 final int N = mBackupParticipants.size(); 1137 for (int i = 0; i < N; i++) { 1138 HashSet<String> participants = mBackupParticipants.valueAt(i); 1139 if (participants != null) { 1140 for (String packageName : participants) { 1141 dataChangedImpl(packageName); 1142 } 1143 } 1144 } 1145 } 1146 } 1147 1148 private TransportManager.TransportBoundListener mTransportBoundListener = 1149 new TransportManager.TransportBoundListener() { 1150 @Override 1151 public boolean onTransportBound(IBackupTransport transport) { 1152 // If the init sentinel file exists, we need to be sure to perform the init 1153 // as soon as practical. We also create the state directory at registration 1154 // time to ensure it's present from the outset. 1155 String name = null; 1156 try { 1157 name = transport.name(); 1158 String transportDirName = transport.transportDirName(); 1159 File stateDir = new File(mBaseStateDir, transportDirName); 1160 stateDir.mkdirs(); 1161 1162 File initSentinel = new File(stateDir, INIT_SENTINEL_FILE_NAME); 1163 if (initSentinel.exists()) { 1164 synchronized (mQueueLock) { 1165 mPendingInits.add(name); 1166 1167 // TODO: pick a better starting time than now + 1 minute 1168 long delay = 1000 * 60; // one minute, in milliseconds 1169 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 1170 System.currentTimeMillis() + delay, mRunInitIntent); 1171 } 1172 } 1173 return true; 1174 } catch (Exception e) { 1175 // the transport threw when asked its file naming prefs; declare it invalid 1176 Slog.w(TAG, "Failed to regiser transport: " + name); 1177 return false; 1178 } 1179 } 1180 }; 1181 1182 // ----- Track installation/removal of packages ----- 1183 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 1184 public void onReceive(Context context, Intent intent) { 1185 if (MORE_DEBUG) Slog.d(TAG, "Received broadcast " + intent); 1186 1187 String action = intent.getAction(); 1188 boolean replacing = false; 1189 boolean added = false; 1190 boolean changed = false; 1191 Bundle extras = intent.getExtras(); 1192 String pkgList[] = null; 1193 if (Intent.ACTION_PACKAGE_ADDED.equals(action) || 1194 Intent.ACTION_PACKAGE_REMOVED.equals(action) || 1195 Intent.ACTION_PACKAGE_CHANGED.equals(action)) { 1196 Uri uri = intent.getData(); 1197 if (uri == null) { 1198 return; 1199 } 1200 final String pkgName = uri.getSchemeSpecificPart(); 1201 if (pkgName != null) { 1202 pkgList = new String[]{pkgName}; 1203 } 1204 changed = Intent.ACTION_PACKAGE_CHANGED.equals(action); 1205 1206 // At package-changed we only care about looking at new transport states 1207 if (changed) { 1208 final String[] components = 1209 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); 1210 1211 if (MORE_DEBUG) { 1212 Slog.i(TAG, "Package " + pkgName + " changed; rechecking"); 1213 for (int i = 0; i < components.length; i++) { 1214 Slog.i(TAG, " * " + components[i]); 1215 } 1216 } 1217 1218 mBackupHandler.post( 1219 () -> mTransportManager.onPackageChanged(pkgName, components)); 1220 return; // nothing more to do in the PACKAGE_CHANGED case 1221 } 1222 1223 added = Intent.ACTION_PACKAGE_ADDED.equals(action); 1224 replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false); 1225 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) { 1226 added = true; 1227 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 1228 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { 1229 added = false; 1230 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 1231 } 1232 1233 if (pkgList == null || pkgList.length == 0) { 1234 return; 1235 } 1236 1237 final int uid = extras.getInt(Intent.EXTRA_UID); 1238 if (added) { 1239 synchronized (mBackupParticipants) { 1240 if (replacing) { 1241 // This is the package-replaced case; we just remove the entry 1242 // under the old uid and fall through to re-add. If an app 1243 // just added key/value backup participation, this picks it up 1244 // as a known participant. 1245 removePackageParticipantsLocked(pkgList, uid); 1246 } 1247 addPackageParticipantsLocked(pkgList); 1248 } 1249 // If they're full-backup candidates, add them there instead 1250 final long now = System.currentTimeMillis(); 1251 for (final String packageName : pkgList) { 1252 try { 1253 PackageInfo app = mPackageManager.getPackageInfo(packageName, 0); 1254 if (AppBackupUtils.appGetsFullBackup(app) 1255 && AppBackupUtils.appIsEligibleForBackup( 1256 app.applicationInfo)) { 1257 enqueueFullBackup(packageName, now); 1258 scheduleNextFullBackupJob(0); 1259 } else { 1260 // The app might have just transitioned out of full-data into 1261 // doing key/value backups, or might have just disabled backups 1262 // entirely. Make sure it is no longer in the full-data queue. 1263 synchronized (mQueueLock) { 1264 dequeueFullBackupLocked(packageName); 1265 } 1266 writeFullBackupScheduleAsync(); 1267 } 1268 1269 mBackupHandler.post( 1270 () -> mTransportManager.onPackageAdded(packageName)); 1271 1272 } catch (NameNotFoundException e) { 1273 // doesn't really exist; ignore it 1274 if (DEBUG) { 1275 Slog.w(TAG, "Can't resolve new app " + packageName); 1276 } 1277 } 1278 } 1279 1280 // Whenever a package is added or updated we need to update 1281 // the package metadata bookkeeping. 1282 dataChangedImpl(PACKAGE_MANAGER_SENTINEL); 1283 } else { 1284 if (replacing) { 1285 // The package is being updated. We'll receive a PACKAGE_ADDED shortly. 1286 } else { 1287 // Outright removal. In the full-data case, the app will be dropped 1288 // from the queue when its (now obsolete) name comes up again for 1289 // backup. 1290 synchronized (mBackupParticipants) { 1291 removePackageParticipantsLocked(pkgList, uid); 1292 } 1293 } 1294 for (final String pkgName : pkgList) { 1295 mBackupHandler.post( 1296 () -> mTransportManager.onPackageRemoved(pkgName)); 1297 } 1298 } 1299 } 1300 }; 1301 1302 // Add the backup agents in the given packages to our set of known backup participants. 1303 // If 'packageNames' is null, adds all backup agents in the whole system. 1304 private void addPackageParticipantsLocked(String[] packageNames) { 1305 // Look for apps that define the android:backupAgent attribute 1306 List<PackageInfo> targetApps = allAgentPackages(); 1307 if (packageNames != null) { 1308 if (MORE_DEBUG) Slog.v(TAG, "addPackageParticipantsLocked: #" + packageNames.length); 1309 for (String packageName : packageNames) { 1310 addPackageParticipantsLockedInner(packageName, targetApps); 1311 } 1312 } else { 1313 if (MORE_DEBUG) Slog.v(TAG, "addPackageParticipantsLocked: all"); 1314 addPackageParticipantsLockedInner(null, targetApps); 1315 } 1316 } 1317 1318 private void addPackageParticipantsLockedInner(String packageName, 1319 List<PackageInfo> targetPkgs) { 1320 if (MORE_DEBUG) { 1321 Slog.v(TAG, "Examining " + packageName + " for backup agent"); 1322 } 1323 1324 for (PackageInfo pkg : targetPkgs) { 1325 if (packageName == null || pkg.packageName.equals(packageName)) { 1326 int uid = pkg.applicationInfo.uid; 1327 HashSet<String> set = mBackupParticipants.get(uid); 1328 if (set == null) { 1329 set = new HashSet<>(); 1330 mBackupParticipants.put(uid, set); 1331 } 1332 set.add(pkg.packageName); 1333 if (MORE_DEBUG) Slog.v(TAG, "Agent found; added"); 1334 1335 // Schedule a backup for it on general principles 1336 if (MORE_DEBUG) Slog.i(TAG, "Scheduling backup for new app " + pkg.packageName); 1337 Message msg = mBackupHandler 1338 .obtainMessage(MSG_SCHEDULE_BACKUP_PACKAGE, pkg.packageName); 1339 mBackupHandler.sendMessage(msg); 1340 } 1341 } 1342 } 1343 1344 // Remove the given packages' entries from our known active set. 1345 private void removePackageParticipantsLocked(String[] packageNames, int oldUid) { 1346 if (packageNames == null) { 1347 Slog.w(TAG, "removePackageParticipants with null list"); 1348 return; 1349 } 1350 1351 if (MORE_DEBUG) { 1352 Slog.v(TAG, "removePackageParticipantsLocked: uid=" + oldUid 1353 + " #" + packageNames.length); 1354 } 1355 for (String pkg : packageNames) { 1356 // Known previous UID, so we know which package set to check 1357 HashSet<String> set = mBackupParticipants.get(oldUid); 1358 if (set != null && set.contains(pkg)) { 1359 removePackageFromSetLocked(set, pkg); 1360 if (set.isEmpty()) { 1361 if (MORE_DEBUG) Slog.v(TAG, " last one of this uid; purging set"); 1362 mBackupParticipants.remove(oldUid); 1363 } 1364 } 1365 } 1366 } 1367 1368 private void removePackageFromSetLocked(final HashSet<String> set, 1369 final String packageName) { 1370 if (set.contains(packageName)) { 1371 // Found it. Remove this one package from the bookkeeping, and 1372 // if it's the last participating app under this uid we drop the 1373 // (now-empty) set as well. 1374 // Note that we deliberately leave it 'known' in the "ever backed up" 1375 // bookkeeping so that its current-dataset data will be retrieved 1376 // if the app is subsequently reinstalled 1377 if (MORE_DEBUG) Slog.v(TAG, " removing participant " + packageName); 1378 set.remove(packageName); 1379 mPendingBackups.remove(packageName); 1380 } 1381 } 1382 1383 // Returns the set of all applications that define an android:backupAgent attribute 1384 private List<PackageInfo> allAgentPackages() { 1385 // !!! TODO: cache this and regenerate only when necessary 1386 int flags = PackageManager.GET_SIGNATURES; 1387 List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags); 1388 int N = packages.size(); 1389 for (int a = N - 1; a >= 0; a--) { 1390 PackageInfo pkg = packages.get(a); 1391 try { 1392 ApplicationInfo app = pkg.applicationInfo; 1393 if (((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) 1394 || app.backupAgentName == null 1395 || (app.flags & ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0) { 1396 packages.remove(a); 1397 } else { 1398 // we will need the shared library path, so look that up and store it here. 1399 // This is used implicitly when we pass the PackageInfo object off to 1400 // the Activity Manager to launch the app for backup/restore purposes. 1401 app = mPackageManager.getApplicationInfo(pkg.packageName, 1402 PackageManager.GET_SHARED_LIBRARY_FILES); 1403 pkg.applicationInfo.sharedLibraryFiles = app.sharedLibraryFiles; 1404 } 1405 } catch (NameNotFoundException e) { 1406 packages.remove(a); 1407 } 1408 } 1409 return packages; 1410 } 1411 1412 // Called from the backup tasks: record that the given app has been successfully 1413 // backed up at least once. This includes both key/value and full-data backups 1414 // through the transport. 1415 public void logBackupComplete(String packageName) { 1416 if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) return; 1417 1418 synchronized (mEverStoredApps) { 1419 if (!mEverStoredApps.add(packageName)) return; 1420 1421 try (RandomAccessFile out = new RandomAccessFile(mEverStored, "rws")) { 1422 out.seek(out.length()); 1423 out.writeUTF(packageName); 1424 } catch (IOException e) { 1425 Slog.e(TAG, "Can't log backup of " + packageName + " to " + mEverStored); 1426 } 1427 } 1428 } 1429 1430 // Remove our awareness of having ever backed up the given package 1431 void removeEverBackedUp(String packageName) { 1432 if (DEBUG) Slog.v(TAG, "Removing backed-up knowledge of " + packageName); 1433 if (MORE_DEBUG) Slog.v(TAG, "New set:"); 1434 1435 synchronized (mEverStoredApps) { 1436 // Rewrite the file and rename to overwrite. If we reboot in the middle, 1437 // we'll recognize on initialization time that the package no longer 1438 // exists and fix it up then. 1439 File tempKnownFile = new File(mBaseStateDir, "processed.new"); 1440 try (RandomAccessFile known = new RandomAccessFile(tempKnownFile, "rws")) { 1441 mEverStoredApps.remove(packageName); 1442 for (String s : mEverStoredApps) { 1443 known.writeUTF(s); 1444 if (MORE_DEBUG) Slog.v(TAG, " " + s); 1445 } 1446 known.close(); 1447 if (!tempKnownFile.renameTo(mEverStored)) { 1448 throw new IOException("Can't rename " + tempKnownFile + " to " + mEverStored); 1449 } 1450 } catch (IOException e) { 1451 // Bad: we couldn't create the new copy. For safety's sake we 1452 // abandon the whole process and remove all what's-backed-up 1453 // state entirely, meaning we'll force a backup pass for every 1454 // participant on the next boot or [re]install. 1455 Slog.w(TAG, "Error rewriting " + mEverStored, e); 1456 mEverStoredApps.clear(); 1457 tempKnownFile.delete(); 1458 mEverStored.delete(); 1459 } 1460 } 1461 } 1462 1463 // Persistently record the current and ancestral backup tokens as well 1464 // as the set of packages with data [supposedly] available in the 1465 // ancestral dataset. 1466 public void writeRestoreTokens() { 1467 try (RandomAccessFile af = new RandomAccessFile(mTokenFile, "rwd")) { 1468 // First, the version number of this record, for futureproofing 1469 af.writeInt(CURRENT_ANCESTRAL_RECORD_VERSION); 1470 1471 // Write the ancestral and current tokens 1472 af.writeLong(mAncestralToken); 1473 af.writeLong(mCurrentToken); 1474 1475 // Now write the set of ancestral packages 1476 if (mAncestralPackages == null) { 1477 af.writeInt(-1); 1478 } else { 1479 af.writeInt(mAncestralPackages.size()); 1480 if (DEBUG) Slog.v(TAG, "Ancestral packages: " + mAncestralPackages.size()); 1481 for (String pkgName : mAncestralPackages) { 1482 af.writeUTF(pkgName); 1483 if (MORE_DEBUG) Slog.v(TAG, " " + pkgName); 1484 } 1485 } 1486 } catch (IOException e) { 1487 Slog.w(TAG, "Unable to write token file:", e); 1488 } 1489 } 1490 1491 // What name is this transport registered under...? 1492 private String getTransportName(IBackupTransport transport) { 1493 if (MORE_DEBUG) { 1494 Slog.v(TAG, "Searching for transport name of " + transport); 1495 } 1496 return mTransportManager.getTransportName(transport); 1497 } 1498 1499 // fire off a backup agent, blocking until it attaches or times out 1500 @Override 1501 public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) { 1502 IBackupAgent agent = null; 1503 synchronized (mAgentConnectLock) { 1504 mConnecting = true; 1505 mConnectedAgent = null; 1506 try { 1507 if (mActivityManager.bindBackupAgent(app.packageName, mode, 1508 UserHandle.USER_OWNER)) { 1509 Slog.d(TAG, "awaiting agent for " + app); 1510 1511 // success; wait for the agent to arrive 1512 // only wait 10 seconds for the bind to happen 1513 long timeoutMark = System.currentTimeMillis() + TIMEOUT_INTERVAL; 1514 while (mConnecting && mConnectedAgent == null 1515 && (System.currentTimeMillis() < timeoutMark)) { 1516 try { 1517 mAgentConnectLock.wait(5000); 1518 } catch (InterruptedException e) { 1519 // just bail 1520 Slog.w(TAG, "Interrupted: " + e); 1521 mConnecting = false; 1522 mConnectedAgent = null; 1523 } 1524 } 1525 1526 // if we timed out with no connect, abort and move on 1527 if (mConnecting == true) { 1528 Slog.w(TAG, "Timeout waiting for agent " + app); 1529 mConnectedAgent = null; 1530 } 1531 if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent); 1532 agent = mConnectedAgent; 1533 } 1534 } catch (RemoteException e) { 1535 // can't happen - ActivityManager is local 1536 } 1537 } 1538 if (agent == null) { 1539 try { 1540 mActivityManager.clearPendingBackup(); 1541 } catch (RemoteException e) { 1542 // can't happen - ActivityManager is local 1543 } 1544 } 1545 return agent; 1546 } 1547 1548 // clear an application's data, blocking until the operation completes or times out 1549 public void clearApplicationDataSynchronous(String packageName) { 1550 // Don't wipe packages marked allowClearUserData=false 1551 try { 1552 PackageInfo info = mPackageManager.getPackageInfo(packageName, 0); 1553 if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) { 1554 if (MORE_DEBUG) { 1555 Slog.i(TAG, "allowClearUserData=false so not wiping " 1556 + packageName); 1557 } 1558 return; 1559 } 1560 } catch (NameNotFoundException e) { 1561 Slog.w(TAG, "Tried to clear data for " + packageName + " but not found"); 1562 return; 1563 } 1564 1565 ClearDataObserver observer = new ClearDataObserver(this); 1566 1567 synchronized (mClearDataLock) { 1568 mClearingData = true; 1569 try { 1570 mActivityManager.clearApplicationUserData(packageName, observer, 0); 1571 } catch (RemoteException e) { 1572 // can't happen because the activity manager is in this process 1573 } 1574 1575 // only wait 10 seconds for the clear data to happen 1576 long timeoutMark = System.currentTimeMillis() + TIMEOUT_INTERVAL; 1577 while (mClearingData && (System.currentTimeMillis() < timeoutMark)) { 1578 try { 1579 mClearDataLock.wait(5000); 1580 } catch (InterruptedException e) { 1581 // won't happen, but still. 1582 mClearingData = false; 1583 } 1584 } 1585 } 1586 } 1587 1588 // Get the restore-set token for the best-available restore set for this package: 1589 // the active set if possible, else the ancestral one. Returns zero if none available. 1590 @Override 1591 public long getAvailableRestoreToken(String packageName) { 1592 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 1593 "getAvailableRestoreToken"); 1594 1595 long token = mAncestralToken; 1596 synchronized (mQueueLock) { 1597 if (mEverStoredApps.contains(packageName)) { 1598 if (MORE_DEBUG) { 1599 Slog.i(TAG, "App in ever-stored, so using current token"); 1600 } 1601 token = mCurrentToken; 1602 } 1603 } 1604 if (MORE_DEBUG) Slog.i(TAG, "getAvailableRestoreToken() == " + token); 1605 return token; 1606 } 1607 1608 @Override 1609 public int requestBackup(String[] packages, IBackupObserver observer, int flags) { 1610 return requestBackup(packages, observer, null, flags); 1611 } 1612 1613 @Override 1614 public int requestBackup(String[] packages, IBackupObserver observer, 1615 IBackupManagerMonitor monitor, int flags) { 1616 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup"); 1617 1618 if (packages == null || packages.length < 1) { 1619 Slog.e(TAG, "No packages named for backup request"); 1620 BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED); 1621 monitor = BackupManagerMonitorUtils.monitorEvent(monitor, 1622 BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES, 1623 null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null); 1624 throw new IllegalArgumentException("No packages are provided for backup"); 1625 } 1626 1627 if (!mEnabled || !mProvisioned) { 1628 Slog.i(TAG, "Backup requested but e=" + mEnabled + " p=" +mProvisioned); 1629 BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_BACKUP_NOT_ALLOWED); 1630 final int logTag = mProvisioned 1631 ? BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED 1632 : BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED; 1633 monitor = BackupManagerMonitorUtils.monitorEvent(monitor, logTag, null, 1634 BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null); 1635 return BackupManager.ERROR_BACKUP_NOT_ALLOWED; 1636 } 1637 1638 IBackupTransport transport = mTransportManager.getCurrentTransportBinder(); 1639 if (transport == null) { 1640 BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED); 1641 monitor = BackupManagerMonitorUtils.monitorEvent(monitor, 1642 BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL, 1643 null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null); 1644 return BackupManager.ERROR_TRANSPORT_ABORTED; 1645 } 1646 1647 ArrayList<String> fullBackupList = new ArrayList<>(); 1648 ArrayList<String> kvBackupList = new ArrayList<>(); 1649 for (String packageName : packages) { 1650 if (PACKAGE_MANAGER_SENTINEL.equals(packageName)) { 1651 kvBackupList.add(packageName); 1652 continue; 1653 } 1654 try { 1655 PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, 1656 PackageManager.GET_SIGNATURES); 1657 if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo)) { 1658 BackupObserverUtils.sendBackupOnPackageResult(observer, packageName, 1659 BackupManager.ERROR_BACKUP_NOT_ALLOWED); 1660 continue; 1661 } 1662 if (AppBackupUtils.appGetsFullBackup(packageInfo)) { 1663 fullBackupList.add(packageInfo.packageName); 1664 } else { 1665 kvBackupList.add(packageInfo.packageName); 1666 } 1667 } catch (NameNotFoundException e) { 1668 BackupObserverUtils.sendBackupOnPackageResult(observer, packageName, 1669 BackupManager.ERROR_PACKAGE_NOT_FOUND); 1670 } 1671 } 1672 EventLog.writeEvent(EventLogTags.BACKUP_REQUESTED, packages.length, kvBackupList.size(), 1673 fullBackupList.size()); 1674 if (MORE_DEBUG) { 1675 Slog.i(TAG, "Backup requested for " + packages.length + " packages, of them: " + 1676 fullBackupList.size() + " full backups, " + kvBackupList.size() 1677 + " k/v backups"); 1678 } 1679 1680 String dirName; 1681 try { 1682 dirName = transport.transportDirName(); 1683 } catch (Exception e) { 1684 Slog.e(TAG, "Transport unavailable while attempting backup: " + e.getMessage()); 1685 BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED); 1686 return BackupManager.ERROR_TRANSPORT_ABORTED; 1687 } 1688 1689 boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0; 1690 1691 Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP); 1692 msg.obj = new BackupParams(transport, dirName, kvBackupList, fullBackupList, observer, 1693 monitor, true, nonIncrementalBackup); 1694 mBackupHandler.sendMessage(msg); 1695 return BackupManager.SUCCESS; 1696 } 1697 1698 // Cancel all running backups. 1699 @Override 1700 public void cancelBackups() { 1701 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "cancelBackups"); 1702 if (MORE_DEBUG) { 1703 Slog.i(TAG, "cancelBackups() called."); 1704 } 1705 final long oldToken = Binder.clearCallingIdentity(); 1706 try { 1707 List<Integer> operationsToCancel = new ArrayList<>(); 1708 synchronized (mCurrentOpLock) { 1709 for (int i = 0; i < mCurrentOperations.size(); i++) { 1710 Operation op = mCurrentOperations.valueAt(i); 1711 int token = mCurrentOperations.keyAt(i); 1712 if (op.type == OP_TYPE_BACKUP) { 1713 operationsToCancel.add(token); 1714 } 1715 } 1716 } 1717 for (Integer token : operationsToCancel) { 1718 handleCancel(token, true /* cancelAll */); 1719 } 1720 // We don't want the backup jobs to kick in any time soon. 1721 // Reschedules them to run in the distant future. 1722 KeyValueBackupJob.schedule(mContext, BUSY_BACKOFF_MIN_MILLIS); 1723 FullBackupJob.schedule(mContext, 2 * BUSY_BACKOFF_MIN_MILLIS); 1724 } finally { 1725 Binder.restoreCallingIdentity(oldToken); 1726 } 1727 } 1728 1729 @Override 1730 public void prepareOperationTimeout(int token, long interval, BackupRestoreTask callback, 1731 int operationType) { 1732 if (operationType != OP_TYPE_BACKUP_WAIT && operationType != OP_TYPE_RESTORE_WAIT) { 1733 Slog.wtf(TAG, "prepareOperationTimeout() doesn't support operation " + 1734 Integer.toHexString(token) + " of type " + operationType); 1735 return; 1736 } 1737 if (MORE_DEBUG) { 1738 Slog.v(TAG, "starting timeout: token=" + Integer.toHexString(token) 1739 + " interval=" + interval + " callback=" + callback); 1740 } 1741 1742 synchronized (mCurrentOpLock) { 1743 mCurrentOperations.put(token, new Operation(OP_PENDING, callback, operationType)); 1744 Message msg = mBackupHandler.obtainMessage(getMessageIdForOperationType(operationType), 1745 token, 0, callback); 1746 mBackupHandler.sendMessageDelayed(msg, interval); 1747 } 1748 } 1749 1750 private int getMessageIdForOperationType(int operationType) { 1751 switch (operationType) { 1752 case OP_TYPE_BACKUP_WAIT: 1753 return MSG_BACKUP_OPERATION_TIMEOUT; 1754 case OP_TYPE_RESTORE_WAIT: 1755 return MSG_RESTORE_OPERATION_TIMEOUT; 1756 default: 1757 Slog.wtf(TAG, "getMessageIdForOperationType called on invalid operation type: " + 1758 operationType); 1759 return -1; 1760 } 1761 } 1762 1763 public void removeOperation(int token) { 1764 if (MORE_DEBUG) { 1765 Slog.d(TAG, "Removing operation token=" + Integer.toHexString(token)); 1766 } 1767 synchronized (mCurrentOpLock) { 1768 if (mCurrentOperations.get(token) == null) { 1769 Slog.w(TAG, "Duplicate remove for operation. token=" + 1770 Integer.toHexString(token)); 1771 } 1772 mCurrentOperations.remove(token); 1773 } 1774 } 1775 1776 // synchronous waiter case 1777 @Override 1778 public boolean waitUntilOperationComplete(int token) { 1779 if (MORE_DEBUG) { 1780 Slog.i(TAG, "Blocking until operation complete for " 1781 + Integer.toHexString(token)); 1782 } 1783 int finalState = OP_PENDING; 1784 Operation op = null; 1785 synchronized (mCurrentOpLock) { 1786 while (true) { 1787 op = mCurrentOperations.get(token); 1788 if (op == null) { 1789 // mysterious disappearance: treat as success with no callback 1790 break; 1791 } else { 1792 if (op.state == OP_PENDING) { 1793 try { 1794 mCurrentOpLock.wait(); 1795 } catch (InterruptedException e) { 1796 } 1797 // When the wait is notified we loop around and recheck the current state 1798 } else { 1799 if (MORE_DEBUG) { 1800 Slog.d(TAG, "Unblocked waiting for operation token=" + 1801 Integer.toHexString(token)); 1802 } 1803 // No longer pending; we're done 1804 finalState = op.state; 1805 break; 1806 } 1807 } 1808 } 1809 } 1810 1811 removeOperation(token); 1812 if (op != null) { 1813 mBackupHandler.removeMessages(getMessageIdForOperationType(op.type)); 1814 } 1815 if (MORE_DEBUG) { 1816 Slog.v(TAG, "operation " + Integer.toHexString(token) 1817 + " complete: finalState=" + finalState); 1818 } 1819 return finalState == OP_ACKNOWLEDGED; 1820 } 1821 1822 public void handleCancel(int token, boolean cancelAll) { 1823 // Notify any synchronous waiters 1824 Operation op = null; 1825 synchronized (mCurrentOpLock) { 1826 op = mCurrentOperations.get(token); 1827 if (MORE_DEBUG) { 1828 if (op == null) { 1829 Slog.w(TAG, "Cancel of token " + Integer.toHexString(token) 1830 + " but no op found"); 1831 } 1832 } 1833 int state = (op != null) ? op.state : OP_TIMEOUT; 1834 if (state == OP_ACKNOWLEDGED) { 1835 // The operation finished cleanly, so we have nothing more to do. 1836 if (DEBUG) { 1837 Slog.w(TAG, "Operation already got an ack." + 1838 "Should have been removed from mCurrentOperations."); 1839 } 1840 op = null; 1841 mCurrentOperations.delete(token); 1842 } else if (state == OP_PENDING) { 1843 if (DEBUG) Slog.v(TAG, "Cancel: token=" + Integer.toHexString(token)); 1844 op.state = OP_TIMEOUT; 1845 // Can't delete op from mCurrentOperations here. waitUntilOperationComplete may be 1846 // called after we receive cancel here. We need this op's state there. 1847 1848 // Remove all pending timeout messages for this operation type. 1849 mBackupHandler.removeMessages(getMessageIdForOperationType(op.type)); 1850 } 1851 mCurrentOpLock.notifyAll(); 1852 } 1853 1854 // If there's a TimeoutHandler for this event, call it 1855 if (op != null && op.callback != null) { 1856 if (MORE_DEBUG) { 1857 Slog.v(TAG, " Invoking cancel on " + op.callback); 1858 } 1859 op.callback.handleCancel(cancelAll); 1860 } 1861 } 1862 1863 // ----- Back up a set of applications via a worker thread ----- 1864 1865 public boolean isBackupOperationInProgress() { 1866 synchronized (mCurrentOpLock) { 1867 for (int i = 0; i < mCurrentOperations.size(); i++) { 1868 Operation op = mCurrentOperations.valueAt(i); 1869 if (op.type == OP_TYPE_BACKUP && op.state == OP_PENDING) { 1870 return true; 1871 } 1872 } 1873 } 1874 return false; 1875 } 1876 1877 1878 @Override 1879 public void tearDownAgentAndKill(ApplicationInfo app) { 1880 if (app == null) { 1881 // Null means the system package, so just quietly move on. :) 1882 return; 1883 } 1884 1885 try { 1886 // unbind and tidy up even on timeout or failure, just in case 1887 mActivityManager.unbindBackupAgent(app); 1888 1889 // The agent was running with a stub Application object, so shut it down. 1890 // !!! We hardcode the confirmation UI's package name here rather than use a 1891 // manifest flag! TODO something less direct. 1892 if (app.uid >= Process.FIRST_APPLICATION_UID 1893 && !app.packageName.equals("com.android.backupconfirm")) { 1894 if (MORE_DEBUG) Slog.d(TAG, "Killing agent host process"); 1895 mActivityManager.killApplicationProcess(app.processName, app.uid); 1896 } else { 1897 if (MORE_DEBUG) Slog.d(TAG, "Not killing after operation: " + app.processName); 1898 } 1899 } catch (RemoteException e) { 1900 Slog.d(TAG, "Lost app trying to shut down"); 1901 } 1902 } 1903 1904 public boolean deviceIsEncrypted() { 1905 try { 1906 return mStorageManager.getEncryptionState() 1907 != StorageManager.ENCRYPTION_STATE_NONE 1908 && mStorageManager.getPasswordType() 1909 != StorageManager.CRYPT_TYPE_DEFAULT; 1910 } catch (Exception e) { 1911 // If we can't talk to the storagemanager service we have a serious problem; fail 1912 // "secure" i.e. assuming that the device is encrypted. 1913 Slog.e(TAG, "Unable to communicate with storagemanager service: " + e.getMessage()); 1914 return true; 1915 } 1916 } 1917 1918 // ----- Full-data backup scheduling ----- 1919 1920 /** 1921 * Schedule a job to tell us when it's a good time to run a full backup 1922 */ 1923 public void scheduleNextFullBackupJob(long transportMinLatency) { 1924 synchronized (mQueueLock) { 1925 if (mFullBackupQueue.size() > 0) { 1926 // schedule the next job at the point in the future when the least-recently 1927 // backed up app comes due for backup again; or immediately if it's already 1928 // due. 1929 final long upcomingLastBackup = mFullBackupQueue.get(0).lastBackup; 1930 final long timeSinceLast = System.currentTimeMillis() - upcomingLastBackup; 1931 final long appLatency = (timeSinceLast < MIN_FULL_BACKUP_INTERVAL) 1932 ? (MIN_FULL_BACKUP_INTERVAL - timeSinceLast) : 0; 1933 final long latency = Math.max(transportMinLatency, appLatency); 1934 Runnable r = new Runnable() { 1935 @Override 1936 public void run() { 1937 FullBackupJob.schedule(mContext, latency); 1938 } 1939 }; 1940 mBackupHandler.postDelayed(r, 2500); 1941 } else { 1942 if (DEBUG_SCHEDULING) { 1943 Slog.i(TAG, "Full backup queue empty; not scheduling"); 1944 } 1945 } 1946 } 1947 } 1948 1949 /** 1950 * Remove a package from the full-data queue. 1951 */ 1952 private void dequeueFullBackupLocked(String packageName) { 1953 final int N = mFullBackupQueue.size(); 1954 for (int i = N - 1; i >= 0; i--) { 1955 final FullBackupEntry e = mFullBackupQueue.get(i); 1956 if (packageName.equals(e.packageName)) { 1957 mFullBackupQueue.remove(i); 1958 } 1959 } 1960 } 1961 1962 /** 1963 * Enqueue full backup for the given app, with a note about when it last ran. 1964 */ 1965 public void enqueueFullBackup(String packageName, long lastBackedUp) { 1966 FullBackupEntry newEntry = new FullBackupEntry(packageName, lastBackedUp); 1967 synchronized (mQueueLock) { 1968 // First, sanity check that we aren't adding a duplicate. Slow but 1969 // straightforward; we'll have at most on the order of a few hundred 1970 // items in this list. 1971 dequeueFullBackupLocked(packageName); 1972 1973 // This is also slow but easy for modest numbers of apps: work backwards 1974 // from the end of the queue until we find an item whose last backup 1975 // time was before this one, then insert this new entry after it. If we're 1976 // adding something new we don't bother scanning, and just prepend. 1977 int which = -1; 1978 if (lastBackedUp > 0) { 1979 for (which = mFullBackupQueue.size() - 1; which >= 0; which--) { 1980 final FullBackupEntry entry = mFullBackupQueue.get(which); 1981 if (entry.lastBackup <= lastBackedUp) { 1982 mFullBackupQueue.add(which + 1, newEntry); 1983 break; 1984 } 1985 } 1986 } 1987 if (which < 0) { 1988 // this one is earlier than any existing one, so prepend 1989 mFullBackupQueue.add(0, newEntry); 1990 } 1991 } 1992 writeFullBackupScheduleAsync(); 1993 } 1994 1995 private boolean fullBackupAllowable(IBackupTransport transport) { 1996 if (transport == null) { 1997 Slog.w(TAG, "Transport not present; full data backup not performed"); 1998 return false; 1999 } 2000 2001 // Don't proceed unless we have already established package metadata 2002 // for the current dataset via a key/value backup pass. 2003 try { 2004 File stateDir = new File(mBaseStateDir, transport.transportDirName()); 2005 File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL); 2006 if (pmState.length() <= 0) { 2007 if (DEBUG) { 2008 Slog.i(TAG, "Full backup requested but dataset not yet initialized"); 2009 } 2010 return false; 2011 } 2012 } catch (Exception e) { 2013 Slog.w(TAG, "Unable to get transport name: " + e.getMessage()); 2014 return false; 2015 } 2016 2017 return true; 2018 } 2019 2020 /** 2021 * Conditions are right for a full backup operation, so run one. The model we use is 2022 * to perform one app backup per scheduled job execution, and to reschedule the job 2023 * with zero latency as long as conditions remain right and we still have work to do. 2024 * 2025 * <p>This is the "start a full backup operation" entry point called by the scheduled job. 2026 * 2027 * @return Whether ongoing work will continue. The return value here will be passed 2028 * along as the return value to the scheduled job's onStartJob() callback. 2029 */ 2030 @Override 2031 public boolean beginFullBackup(FullBackupJob scheduledJob) { 2032 long now = System.currentTimeMillis(); 2033 FullBackupEntry entry = null; 2034 long latency = MIN_FULL_BACKUP_INTERVAL; 2035 2036 if (!mEnabled || !mProvisioned) { 2037 // Backups are globally disabled, so don't proceed. We also don't reschedule 2038 // the job driving automatic backups; that job will be scheduled again when 2039 // the user enables backup. 2040 if (MORE_DEBUG) { 2041 Slog.i(TAG, "beginFullBackup but e=" + mEnabled 2042 + " p=" + mProvisioned + "; ignoring"); 2043 } 2044 return false; 2045 } 2046 2047 // Don't run the backup if we're in battery saver mode, but reschedule 2048 // to try again in the not-so-distant future. 2049 final PowerSaveState result = 2050 mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP); 2051 if (result.batterySaverEnabled) { 2052 if (DEBUG) Slog.i(TAG, "Deferring scheduled full backups in battery saver mode"); 2053 FullBackupJob.schedule(mContext, KeyValueBackupJob.BATCH_INTERVAL); 2054 return false; 2055 } 2056 2057 if (DEBUG_SCHEDULING) { 2058 Slog.i(TAG, "Beginning scheduled full backup operation"); 2059 } 2060 2061 // Great; we're able to run full backup jobs now. See if we have any work to do. 2062 synchronized (mQueueLock) { 2063 if (mRunningFullBackupTask != null) { 2064 Slog.e(TAG, "Backup triggered but one already/still running!"); 2065 return false; 2066 } 2067 2068 // At this point we think that we have work to do, but possibly not right now. 2069 // Any exit without actually running backups will also require that we 2070 // reschedule the job. 2071 boolean runBackup = true; 2072 boolean headBusy; 2073 2074 do { 2075 // Recheck each time, because culling due to ineligibility may 2076 // have emptied the queue. 2077 if (mFullBackupQueue.size() == 0) { 2078 // no work to do so just bow out 2079 if (DEBUG) { 2080 Slog.i(TAG, "Backup queue empty; doing nothing"); 2081 } 2082 runBackup = false; 2083 break; 2084 } 2085 2086 headBusy = false; 2087 2088 if (!fullBackupAllowable(mTransportManager.getCurrentTransportBinder())) { 2089 if (MORE_DEBUG) { 2090 Slog.i(TAG, "Preconditions not met; not running full backup"); 2091 } 2092 runBackup = false; 2093 // Typically this means we haven't run a key/value backup yet. Back off 2094 // full-backup operations by the key/value job's run interval so that 2095 // next time we run, we are likely to be able to make progress. 2096 latency = KeyValueBackupJob.BATCH_INTERVAL; 2097 } 2098 2099 if (runBackup) { 2100 entry = mFullBackupQueue.get(0); 2101 long timeSinceRun = now - entry.lastBackup; 2102 runBackup = (timeSinceRun >= MIN_FULL_BACKUP_INTERVAL); 2103 if (!runBackup) { 2104 // It's too early to back up the next thing in the queue, so bow out 2105 if (MORE_DEBUG) { 2106 Slog.i(TAG, "Device ready but too early to back up next app"); 2107 } 2108 // Wait until the next app in the queue falls due for a full data backup 2109 latency = MIN_FULL_BACKUP_INTERVAL - timeSinceRun; 2110 break; // we know we aren't doing work yet, so bail. 2111 } 2112 2113 try { 2114 PackageInfo appInfo = mPackageManager.getPackageInfo(entry.packageName, 0); 2115 if (!AppBackupUtils.appGetsFullBackup(appInfo)) { 2116 // The head app isn't supposed to get full-data backups [any more]; 2117 // so we cull it and force a loop around to consider the new head 2118 // app. 2119 if (MORE_DEBUG) { 2120 Slog.i(TAG, "Culling package " + entry.packageName 2121 + " in full-backup queue but not eligible"); 2122 } 2123 mFullBackupQueue.remove(0); 2124 headBusy = true; // force the while() condition 2125 continue; 2126 } 2127 2128 final int privFlags = appInfo.applicationInfo.privateFlags; 2129 headBusy = (privFlags & PRIVATE_FLAG_BACKUP_IN_FOREGROUND) == 0 2130 && mActivityManager.isAppForeground(appInfo.applicationInfo.uid); 2131 2132 if (headBusy) { 2133 final long nextEligible = System.currentTimeMillis() 2134 + BUSY_BACKOFF_MIN_MILLIS 2135 + mTokenGenerator.nextInt(BUSY_BACKOFF_FUZZ); 2136 if (DEBUG_SCHEDULING) { 2137 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 2138 Slog.i(TAG, "Full backup time but " + entry.packageName 2139 + " is busy; deferring to " 2140 + sdf.format(new Date(nextEligible))); 2141 } 2142 // This relocates the app's entry from the head of the queue to 2143 // its order-appropriate position further down, so upon looping 2144 // a new candidate will be considered at the head. 2145 enqueueFullBackup(entry.packageName, 2146 nextEligible - MIN_FULL_BACKUP_INTERVAL); 2147 } 2148 } catch (NameNotFoundException nnf) { 2149 // So, we think we want to back this up, but it turns out the package 2150 // in question is no longer installed. We want to drop it from the 2151 // queue entirely and move on, but if there's nothing else in the queue 2152 // we should bail entirely. headBusy cannot have been set to true yet. 2153 runBackup = (mFullBackupQueue.size() > 1); 2154 } catch (RemoteException e) { 2155 // Cannot happen; the Activity Manager is in the same process 2156 } 2157 } 2158 } while (headBusy); 2159 2160 if (!runBackup) { 2161 if (DEBUG_SCHEDULING) { 2162 Slog.i(TAG, "Nothing pending full backup; rescheduling +" + latency); 2163 } 2164 final long deferTime = latency; // pin for the closure 2165 mBackupHandler.post(new Runnable() { 2166 @Override 2167 public void run() { 2168 FullBackupJob.schedule(mContext, deferTime); 2169 } 2170 }); 2171 return false; 2172 } 2173 2174 // Okay, the top thing is ready for backup now. Do it. 2175 mFullBackupQueue.remove(0); 2176 CountDownLatch latch = new CountDownLatch(1); 2177 String[] pkg = new String[]{entry.packageName}; 2178 mRunningFullBackupTask = new PerformFullTransportBackupTask(this, null, pkg, true, 2179 scheduledJob, latch, null, null, false /* userInitiated */); 2180 // Acquiring wakelock for PerformFullTransportBackupTask before its start. 2181 mWakelock.acquire(); 2182 (new Thread(mRunningFullBackupTask)).start(); 2183 } 2184 2185 return true; 2186 } 2187 2188 // The job scheduler says our constraints don't hold any more, 2189 // so tear down any ongoing backup task right away. 2190 @Override 2191 public void endFullBackup() { 2192 synchronized (mQueueLock) { 2193 if (mRunningFullBackupTask != null) { 2194 if (DEBUG_SCHEDULING) { 2195 Slog.i(TAG, "Telling running backup to stop"); 2196 } 2197 mRunningFullBackupTask.handleCancel(true); 2198 } 2199 } 2200 } 2201 2202 // Used by both incremental and full restore 2203 public void restoreWidgetData(String packageName, byte[] widgetData) { 2204 // Apply the restored widget state and generate the ID update for the app 2205 // TODO: http://b/22388012 2206 if (MORE_DEBUG) { 2207 Slog.i(TAG, "Incorporating restored widget data"); 2208 } 2209 AppWidgetBackupBridge.restoreWidgetState(packageName, widgetData, UserHandle.USER_SYSTEM); 2210 } 2211 2212 // ***************************** 2213 // NEW UNIFIED RESTORE IMPLEMENTATION 2214 // ***************************** 2215 2216 public void dataChangedImpl(String packageName) { 2217 HashSet<String> targets = dataChangedTargets(packageName); 2218 dataChangedImpl(packageName, targets); 2219 } 2220 2221 private void dataChangedImpl(String packageName, HashSet<String> targets) { 2222 // Record that we need a backup pass for the caller. Since multiple callers 2223 // may share a uid, we need to note all candidates within that uid and schedule 2224 // a backup pass for each of them. 2225 if (targets == null) { 2226 Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'" 2227 + " uid=" + Binder.getCallingUid()); 2228 return; 2229 } 2230 2231 synchronized (mQueueLock) { 2232 // Note that this client has made data changes that need to be backed up 2233 if (targets.contains(packageName)) { 2234 // Add the caller to the set of pending backups. If there is 2235 // one already there, then overwrite it, but no harm done. 2236 BackupRequest req = new BackupRequest(packageName); 2237 if (mPendingBackups.put(packageName, req) == null) { 2238 if (MORE_DEBUG) Slog.d(TAG, "Now staging backup of " + packageName); 2239 2240 // Journal this request in case of crash. The put() 2241 // operation returned null when this package was not already 2242 // in the set; we want to avoid touching the disk redundantly. 2243 writeToJournalLocked(packageName); 2244 } 2245 } 2246 } 2247 2248 // ...and schedule a backup pass if necessary 2249 KeyValueBackupJob.schedule(mContext); 2250 } 2251 2252 // Note: packageName is currently unused, but may be in the future 2253 private HashSet<String> dataChangedTargets(String packageName) { 2254 // If the caller does not hold the BACKUP permission, it can only request a 2255 // backup of its own data. 2256 if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(), 2257 Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) { 2258 synchronized (mBackupParticipants) { 2259 return mBackupParticipants.get(Binder.getCallingUid()); 2260 } 2261 } 2262 2263 // a caller with full permission can ask to back up any participating app 2264 if (PACKAGE_MANAGER_SENTINEL.equals(packageName)) { 2265 return Sets.newHashSet(PACKAGE_MANAGER_SENTINEL); 2266 } else { 2267 synchronized (mBackupParticipants) { 2268 return SparseArrayUtils.union(mBackupParticipants); 2269 } 2270 } 2271 } 2272 2273 private void writeToJournalLocked(String str) { 2274 try { 2275 if (mJournal == null) mJournal = DataChangedJournal.newJournal(mJournalDir); 2276 mJournal.addPackage(str); 2277 } catch (IOException e) { 2278 Slog.e(TAG, "Can't write " + str + " to backup journal", e); 2279 mJournal = null; 2280 } 2281 } 2282 2283 // ----- IBackupManager binder interface ----- 2284 2285 @Override 2286 public void dataChanged(final String packageName) { 2287 final int callingUserHandle = UserHandle.getCallingUserId(); 2288 if (callingUserHandle != UserHandle.USER_SYSTEM) { 2289 // TODO: http://b/22388012 2290 // App is running under a non-owner user profile. For now, we do not back 2291 // up data from secondary user profiles. 2292 // TODO: backups for all user profiles although don't add backup for profiles 2293 // without adding admin control in DevicePolicyManager. 2294 if (MORE_DEBUG) { 2295 Slog.v(TAG, "dataChanged(" + packageName + ") ignored because it's user " 2296 + callingUserHandle); 2297 } 2298 return; 2299 } 2300 2301 final HashSet<String> targets = dataChangedTargets(packageName); 2302 if (targets == null) { 2303 Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'" 2304 + " uid=" + Binder.getCallingUid()); 2305 return; 2306 } 2307 2308 mBackupHandler.post(new Runnable() { 2309 public void run() { 2310 dataChangedImpl(packageName, targets); 2311 } 2312 }); 2313 } 2314 2315 // Run an initialize operation for the given transport 2316 @Override 2317 public void initializeTransports(String[] transportNames, IBackupObserver observer) { 2318 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "initializeTransport"); 2319 if (MORE_DEBUG || true) { 2320 Slog.v(TAG, "initializeTransport(): " + Arrays.asList(transportNames)); 2321 } 2322 2323 final long oldId = Binder.clearCallingIdentity(); 2324 try { 2325 mWakelock.acquire(); 2326 mBackupHandler.post(new PerformInitializeTask(this, transportNames, observer)); 2327 } finally { 2328 Binder.restoreCallingIdentity(oldId); 2329 } 2330 } 2331 2332 // Clear the given package's backup data from the current transport 2333 @Override 2334 public void clearBackupData(String transportName, String packageName) { 2335 if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName + " on " + transportName); 2336 PackageInfo info; 2337 try { 2338 info = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); 2339 } catch (NameNotFoundException e) { 2340 Slog.d(TAG, "No such package '" + packageName + "' - not clearing backup data"); 2341 return; 2342 } 2343 2344 // If the caller does not hold the BACKUP permission, it can only request a 2345 // wipe of its own backed-up data. 2346 HashSet<String> apps; 2347 if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(), 2348 Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) { 2349 apps = mBackupParticipants.get(Binder.getCallingUid()); 2350 } else { 2351 // a caller with full permission can ask to back up any participating app 2352 // !!! TODO: allow data-clear of ANY app? 2353 if (MORE_DEBUG) Slog.v(TAG, "Privileged caller, allowing clear of other apps"); 2354 apps = SparseArrayUtils.union(mBackupParticipants); 2355 } 2356 2357 // Is the given app an available participant? 2358 if (apps.contains(packageName)) { 2359 // found it; fire off the clear request 2360 if (MORE_DEBUG) Slog.v(TAG, "Found the app - running clear process"); 2361 mBackupHandler.removeMessages(MSG_RETRY_CLEAR); 2362 synchronized (mQueueLock) { 2363 final IBackupTransport transport = 2364 mTransportManager.getTransportBinder(transportName); 2365 if (transport == null) { 2366 // transport is currently unavailable -- make sure to retry 2367 Message msg = mBackupHandler.obtainMessage(MSG_RETRY_CLEAR, 2368 new ClearRetryParams(transportName, packageName)); 2369 mBackupHandler.sendMessageDelayed(msg, TRANSPORT_RETRY_INTERVAL); 2370 return; 2371 } 2372 long oldId = Binder.clearCallingIdentity(); 2373 mWakelock.acquire(); 2374 Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR, 2375 new ClearParams(transport, info)); 2376 mBackupHandler.sendMessage(msg); 2377 Binder.restoreCallingIdentity(oldId); 2378 } 2379 } 2380 } 2381 2382 // Run a backup pass immediately for any applications that have declared 2383 // that they have pending updates. 2384 @Override 2385 public void backupNow() { 2386 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow"); 2387 2388 final PowerSaveState result = 2389 mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP); 2390 if (result.batterySaverEnabled) { 2391 if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode"); 2392 KeyValueBackupJob.schedule(mContext); // try again in several hours 2393 } else { 2394 if (DEBUG) Slog.v(TAG, "Scheduling immediate backup pass"); 2395 synchronized (mQueueLock) { 2396 // Fire the intent that kicks off the whole shebang... 2397 try { 2398 mRunBackupIntent.send(); 2399 } catch (PendingIntent.CanceledException e) { 2400 // should never happen 2401 Slog.e(TAG, "run-backup intent cancelled!"); 2402 } 2403 2404 // ...and cancel any pending scheduled job, because we've just superseded it 2405 KeyValueBackupJob.cancel(mContext); 2406 } 2407 } 2408 } 2409 2410 public boolean deviceIsProvisioned() { 2411 final ContentResolver resolver = mContext.getContentResolver(); 2412 return (Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0); 2413 } 2414 2415 // Run a backup pass for the given packages, writing the resulting data stream 2416 // to the supplied file descriptor. This method is synchronous and does not return 2417 // to the caller until the backup has been completed. 2418 // 2419 // This is the variant used by 'adb backup'; it requires on-screen confirmation 2420 // by the user because it can be used to offload data over untrusted USB. 2421 @Override 2422 public void adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, 2423 boolean includeShared, boolean doWidgets, boolean doAllApps, boolean includeSystem, 2424 boolean compress, boolean doKeyValue, String[] pkgList) { 2425 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbBackup"); 2426 2427 final int callingUserHandle = UserHandle.getCallingUserId(); 2428 // TODO: http://b/22388012 2429 if (callingUserHandle != UserHandle.USER_SYSTEM) { 2430 throw new IllegalStateException("Backup supported only for the device owner"); 2431 } 2432 2433 // Validate 2434 if (!doAllApps) { 2435 if (!includeShared) { 2436 // If we're backing up shared data (sdcard or equivalent), then we can run 2437 // without any supplied app names. Otherwise, we'd be doing no work, so 2438 // report the error. 2439 if (pkgList == null || pkgList.length == 0) { 2440 throw new IllegalArgumentException( 2441 "Backup requested but neither shared nor any apps named"); 2442 } 2443 } 2444 } 2445 2446 long oldId = Binder.clearCallingIdentity(); 2447 try { 2448 // Doesn't make sense to do a full backup prior to setup 2449 if (!deviceIsProvisioned()) { 2450 Slog.i(TAG, "Backup not supported before setup"); 2451 return; 2452 } 2453 2454 if (DEBUG) { 2455 Slog.v(TAG, "Requesting backup: apks=" + includeApks + " obb=" + includeObbs 2456 + " shared=" + includeShared + " all=" + doAllApps + " system=" 2457 + includeSystem + " includekeyvalue=" + doKeyValue + " pkgs=" + pkgList); 2458 } 2459 Slog.i(TAG, "Beginning adb backup..."); 2460 2461 AdbBackupParams params = new AdbBackupParams(fd, includeApks, includeObbs, 2462 includeShared, doWidgets, doAllApps, includeSystem, compress, doKeyValue, 2463 pkgList); 2464 final int token = generateRandomIntegerToken(); 2465 synchronized (mAdbBackupRestoreConfirmations) { 2466 mAdbBackupRestoreConfirmations.put(token, params); 2467 } 2468 2469 // start up the confirmation UI 2470 if (DEBUG) Slog.d(TAG, "Starting backup confirmation UI, token=" + token); 2471 if (!startConfirmationUi(token, FullBackup.FULL_BACKUP_INTENT_ACTION)) { 2472 Slog.e(TAG, "Unable to launch backup confirmation UI"); 2473 mAdbBackupRestoreConfirmations.delete(token); 2474 return; 2475 } 2476 2477 // make sure the screen is lit for the user interaction 2478 mPowerManager.userActivity(SystemClock.uptimeMillis(), 2479 PowerManager.USER_ACTIVITY_EVENT_OTHER, 2480 0); 2481 2482 // start the confirmation countdown 2483 startConfirmationTimeout(token, params); 2484 2485 // wait for the backup to be performed 2486 if (DEBUG) Slog.d(TAG, "Waiting for backup completion..."); 2487 waitForCompletion(params); 2488 } finally { 2489 try { 2490 fd.close(); 2491 } catch (IOException e) { 2492 Slog.e(TAG, "IO error closing output for adb backup: " + e.getMessage()); 2493 } 2494 Binder.restoreCallingIdentity(oldId); 2495 Slog.d(TAG, "Adb backup processing complete."); 2496 } 2497 } 2498 2499 @Override 2500 public void fullTransportBackup(String[] pkgNames) { 2501 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, 2502 "fullTransportBackup"); 2503 2504 final int callingUserHandle = UserHandle.getCallingUserId(); 2505 // TODO: http://b/22388012 2506 if (callingUserHandle != UserHandle.USER_SYSTEM) { 2507 throw new IllegalStateException("Restore supported only for the device owner"); 2508 } 2509 2510 if (!fullBackupAllowable(mTransportManager.getCurrentTransportBinder())) { 2511 Slog.i(TAG, "Full backup not currently possible -- key/value backup not yet run?"); 2512 } else { 2513 if (DEBUG) { 2514 Slog.d(TAG, "fullTransportBackup()"); 2515 } 2516 2517 final long oldId = Binder.clearCallingIdentity(); 2518 try { 2519 CountDownLatch latch = new CountDownLatch(1); 2520 PerformFullTransportBackupTask task = new PerformFullTransportBackupTask(this, null, 2521 pkgNames, false, null, latch, null, null, false /* userInitiated */); 2522 // Acquiring wakelock for PerformFullTransportBackupTask before its start. 2523 mWakelock.acquire(); 2524 (new Thread(task, "full-transport-master")).start(); 2525 do { 2526 try { 2527 latch.await(); 2528 break; 2529 } catch (InterruptedException e) { 2530 // Just go back to waiting for the latch to indicate completion 2531 } 2532 } while (true); 2533 2534 // We just ran a backup on these packages, so kick them to the end of the queue 2535 final long now = System.currentTimeMillis(); 2536 for (String pkg : pkgNames) { 2537 enqueueFullBackup(pkg, now); 2538 } 2539 } finally { 2540 Binder.restoreCallingIdentity(oldId); 2541 } 2542 } 2543 2544 if (DEBUG) { 2545 Slog.d(TAG, "Done with full transport backup."); 2546 } 2547 } 2548 2549 @Override 2550 public void adbRestore(ParcelFileDescriptor fd) { 2551 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbRestore"); 2552 2553 final int callingUserHandle = UserHandle.getCallingUserId(); 2554 // TODO: http://b/22388012 2555 if (callingUserHandle != UserHandle.USER_SYSTEM) { 2556 throw new IllegalStateException("Restore supported only for the device owner"); 2557 } 2558 2559 long oldId = Binder.clearCallingIdentity(); 2560 2561 try { 2562 // Check whether the device has been provisioned -- we don't handle 2563 // full restores prior to completing the setup process. 2564 if (!deviceIsProvisioned()) { 2565 Slog.i(TAG, "Full restore not permitted before setup"); 2566 return; 2567 } 2568 2569 Slog.i(TAG, "Beginning restore..."); 2570 2571 AdbRestoreParams params = new AdbRestoreParams(fd); 2572 final int token = generateRandomIntegerToken(); 2573 synchronized (mAdbBackupRestoreConfirmations) { 2574 mAdbBackupRestoreConfirmations.put(token, params); 2575 } 2576 2577 // start up the confirmation UI 2578 if (DEBUG) Slog.d(TAG, "Starting restore confirmation UI, token=" + token); 2579 if (!startConfirmationUi(token, FullBackup.FULL_RESTORE_INTENT_ACTION)) { 2580 Slog.e(TAG, "Unable to launch restore confirmation"); 2581 mAdbBackupRestoreConfirmations.delete(token); 2582 return; 2583 } 2584 2585 // make sure the screen is lit for the user interaction 2586 mPowerManager.userActivity(SystemClock.uptimeMillis(), 2587 PowerManager.USER_ACTIVITY_EVENT_OTHER, 2588 0); 2589 2590 // start the confirmation countdown 2591 startConfirmationTimeout(token, params); 2592 2593 // wait for the restore to be performed 2594 if (DEBUG) Slog.d(TAG, "Waiting for restore completion..."); 2595 waitForCompletion(params); 2596 } finally { 2597 try { 2598 fd.close(); 2599 } catch (IOException e) { 2600 Slog.w(TAG, "Error trying to close fd after adb restore: " + e); 2601 } 2602 Binder.restoreCallingIdentity(oldId); 2603 Slog.i(TAG, "adb restore processing complete."); 2604 } 2605 } 2606 2607 private boolean startConfirmationUi(int token, String action) { 2608 try { 2609 Intent confIntent = new Intent(action); 2610 confIntent.setClassName("com.android.backupconfirm", 2611 "com.android.backupconfirm.BackupRestoreConfirmation"); 2612 confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token); 2613 confIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2614 mContext.startActivityAsUser(confIntent, UserHandle.SYSTEM); 2615 } catch (ActivityNotFoundException e) { 2616 return false; 2617 } 2618 return true; 2619 } 2620 2621 private void startConfirmationTimeout(int token, AdbParams params) { 2622 if (MORE_DEBUG) { 2623 Slog.d(TAG, "Posting conf timeout msg after " 2624 + TIMEOUT_FULL_CONFIRMATION + " millis"); 2625 } 2626 Message msg = mBackupHandler.obtainMessage(MSG_FULL_CONFIRMATION_TIMEOUT, 2627 token, 0, params); 2628 mBackupHandler.sendMessageDelayed(msg, TIMEOUT_FULL_CONFIRMATION); 2629 } 2630 2631 private void waitForCompletion(AdbParams params) { 2632 synchronized (params.latch) { 2633 while (params.latch.get() == false) { 2634 try { 2635 params.latch.wait(); 2636 } catch (InterruptedException e) { /* never interrupted */ } 2637 } 2638 } 2639 } 2640 2641 public void signalAdbBackupRestoreCompletion(AdbParams params) { 2642 synchronized (params.latch) { 2643 params.latch.set(true); 2644 params.latch.notifyAll(); 2645 } 2646 } 2647 2648 // Confirm that the previously-requested full backup/restore operation can proceed. This 2649 // is used to require a user-facing disclosure about the operation. 2650 @Override 2651 public void acknowledgeAdbBackupOrRestore(int token, boolean allow, 2652 String curPassword, String encPpassword, IFullBackupRestoreObserver observer) { 2653 if (DEBUG) { 2654 Slog.d(TAG, "acknowledgeAdbBackupOrRestore : token=" + token 2655 + " allow=" + allow); 2656 } 2657 2658 // TODO: possibly require not just this signature-only permission, but even 2659 // require that the specific designated confirmation-UI app uid is the caller? 2660 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, 2661 "acknowledgeAdbBackupOrRestore"); 2662 2663 long oldId = Binder.clearCallingIdentity(); 2664 try { 2665 2666 AdbParams params; 2667 synchronized (mAdbBackupRestoreConfirmations) { 2668 params = mAdbBackupRestoreConfirmations.get(token); 2669 if (params != null) { 2670 mBackupHandler.removeMessages(MSG_FULL_CONFIRMATION_TIMEOUT, params); 2671 mAdbBackupRestoreConfirmations.delete(token); 2672 2673 if (allow) { 2674 final int verb = params instanceof AdbBackupParams 2675 ? MSG_RUN_ADB_BACKUP 2676 : MSG_RUN_ADB_RESTORE; 2677 2678 params.observer = observer; 2679 params.curPassword = curPassword; 2680 2681 params.encryptPassword = encPpassword; 2682 2683 if (MORE_DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb); 2684 mWakelock.acquire(); 2685 Message msg = mBackupHandler.obtainMessage(verb, params); 2686 mBackupHandler.sendMessage(msg); 2687 } else { 2688 Slog.w(TAG, "User rejected full backup/restore operation"); 2689 // indicate completion without having actually transferred any data 2690 signalAdbBackupRestoreCompletion(params); 2691 } 2692 } else { 2693 Slog.w(TAG, "Attempted to ack full backup/restore with invalid token"); 2694 } 2695 } 2696 } finally { 2697 Binder.restoreCallingIdentity(oldId); 2698 } 2699 } 2700 2701 private static boolean backupSettingMigrated(int userId) { 2702 File base = new File(Environment.getDataDirectory(), "backup"); 2703 File enableFile = new File(base, BACKUP_ENABLE_FILE); 2704 return enableFile.exists(); 2705 } 2706 2707 private static boolean readBackupEnableState(int userId) { 2708 File base = new File(Environment.getDataDirectory(), "backup"); 2709 File enableFile = new File(base, BACKUP_ENABLE_FILE); 2710 if (enableFile.exists()) { 2711 try (FileInputStream fin = new FileInputStream(enableFile)) { 2712 int state = fin.read(); 2713 return state != 0; 2714 } catch (IOException e) { 2715 // can't read the file; fall through to assume disabled 2716 Slog.e(TAG, "Cannot read enable state; assuming disabled"); 2717 } 2718 } else { 2719 if (DEBUG) { 2720 Slog.i(TAG, "isBackupEnabled() => false due to absent settings file"); 2721 } 2722 } 2723 return false; 2724 } 2725 2726 private static void writeBackupEnableState(boolean enable, int userId) { 2727 File base = new File(Environment.getDataDirectory(), "backup"); 2728 File enableFile = new File(base, BACKUP_ENABLE_FILE); 2729 File stage = new File(base, BACKUP_ENABLE_FILE + "-stage"); 2730 try (FileOutputStream fout = new FileOutputStream(stage)) { 2731 fout.write(enable ? 1 : 0); 2732 fout.close(); 2733 stage.renameTo(enableFile); 2734 // will be synced immediately by the try-with-resources call to close() 2735 } catch (IOException | RuntimeException e) { 2736 // Whoops; looks like we're doomed. Roll everything out, disabled, 2737 // including the legacy state. 2738 Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: " 2739 + e.getMessage()); 2740 2741 final ContentResolver r = sInstance.mContext.getContentResolver(); 2742 Settings.Secure.putStringForUser(r, 2743 Settings.Secure.BACKUP_ENABLED, null, userId); 2744 enableFile.delete(); 2745 stage.delete(); 2746 } 2747 } 2748 2749 // Enable/disable backups 2750 @Override 2751 public void setBackupEnabled(boolean enable) { 2752 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2753 "setBackupEnabled"); 2754 2755 Slog.i(TAG, "Backup enabled => " + enable); 2756 2757 long oldId = Binder.clearCallingIdentity(); 2758 try { 2759 boolean wasEnabled = mEnabled; 2760 synchronized (this) { 2761 writeBackupEnableState(enable, UserHandle.USER_SYSTEM); 2762 mEnabled = enable; 2763 } 2764 2765 synchronized (mQueueLock) { 2766 if (enable && !wasEnabled && mProvisioned) { 2767 // if we've just been enabled, start scheduling backup passes 2768 KeyValueBackupJob.schedule(mContext); 2769 scheduleNextFullBackupJob(0); 2770 } else if (!enable) { 2771 // No longer enabled, so stop running backups 2772 if (MORE_DEBUG) Slog.i(TAG, "Opting out of backup"); 2773 2774 KeyValueBackupJob.cancel(mContext); 2775 2776 // This also constitutes an opt-out, so we wipe any data for 2777 // this device from the backend. We start that process with 2778 // an alarm in order to guarantee wakelock states. 2779 if (wasEnabled && mProvisioned) { 2780 // NOTE: we currently flush every registered transport, not just 2781 // the currently-active one. 2782 String[] allTransports = mTransportManager.getBoundTransportNames(); 2783 // build the set of transports for which we are posting an init 2784 for (String transport : allTransports) { 2785 recordInitPendingLocked(true, transport); 2786 } 2787 mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 2788 mRunInitIntent); 2789 } 2790 } 2791 } 2792 } finally { 2793 Binder.restoreCallingIdentity(oldId); 2794 } 2795 } 2796 2797 // Enable/disable automatic restore of app data at install time 2798 @Override 2799 public void setAutoRestore(boolean doAutoRestore) { 2800 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2801 "setAutoRestore"); 2802 2803 Slog.i(TAG, "Auto restore => " + doAutoRestore); 2804 2805 final long oldId = Binder.clearCallingIdentity(); 2806 try { 2807 synchronized (this) { 2808 Settings.Secure.putInt(mContext.getContentResolver(), 2809 Settings.Secure.BACKUP_AUTO_RESTORE, doAutoRestore ? 1 : 0); 2810 mAutoRestore = doAutoRestore; 2811 } 2812 } finally { 2813 Binder.restoreCallingIdentity(oldId); 2814 } 2815 } 2816 2817 // Mark the backup service as having been provisioned 2818 @Override 2819 public void setBackupProvisioned(boolean available) { 2820 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2821 "setBackupProvisioned"); 2822 /* 2823 * This is now a no-op; provisioning is simply the device's own setup state. 2824 */ 2825 } 2826 2827 // Report whether the backup mechanism is currently enabled 2828 @Override 2829 public boolean isBackupEnabled() { 2830 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2831 "isBackupEnabled"); 2832 return mEnabled; // no need to synchronize just to read it 2833 } 2834 2835 // Report the name of the currently active transport 2836 @Override 2837 public String getCurrentTransport() { 2838 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2839 "getCurrentTransport"); 2840 String currentTransport = mTransportManager.getCurrentTransportName(); 2841 if (MORE_DEBUG) Slog.v(TAG, "... getCurrentTransport() returning " + currentTransport); 2842 return currentTransport; 2843 } 2844 2845 // Report all known, available backup transports 2846 @Override 2847 public String[] listAllTransports() { 2848 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2849 "listAllTransports"); 2850 2851 return mTransportManager.getBoundTransportNames(); 2852 } 2853 2854 @Override 2855 public ComponentName[] listAllTransportComponents() { 2856 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2857 "listAllTransportComponents"); 2858 return mTransportManager.getAllTransportCompenents(); 2859 } 2860 2861 @Override 2862 public String[] getTransportWhitelist() { 2863 // No permission check, intentionally. 2864 Set<ComponentName> whitelistedComponents = mTransportManager.getTransportWhitelist(); 2865 String[] whitelistedTransports = new String[whitelistedComponents.size()]; 2866 int i = 0; 2867 for (ComponentName component : whitelistedComponents) { 2868 whitelistedTransports[i] = component.flattenToShortString(); 2869 i++; 2870 } 2871 return whitelistedTransports; 2872 } 2873 2874 // Select which transport to use for the next backup operation. 2875 @Override 2876 public String selectBackupTransport(String transport) { 2877 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2878 "selectBackupTransport"); 2879 2880 final long oldId = Binder.clearCallingIdentity(); 2881 try { 2882 String prevTransport = mTransportManager.selectTransport(transport); 2883 Settings.Secure.putString(mContext.getContentResolver(), 2884 Settings.Secure.BACKUP_TRANSPORT, transport); 2885 Slog.v(TAG, "selectBackupTransport() set " + mTransportManager.getCurrentTransportName() 2886 + " returning " + prevTransport); 2887 return prevTransport; 2888 } finally { 2889 Binder.restoreCallingIdentity(oldId); 2890 } 2891 } 2892 2893 @Override 2894 public void selectBackupTransportAsync(final ComponentName transport, 2895 final ISelectBackupTransportCallback listener) { 2896 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2897 "selectBackupTransportAsync"); 2898 2899 final long oldId = Binder.clearCallingIdentity(); 2900 2901 Slog.v(TAG, "selectBackupTransportAsync() called with transport " + 2902 transport.flattenToShortString()); 2903 2904 mTransportManager.ensureTransportReady(transport, new SelectBackupTransportCallback() { 2905 @Override 2906 public void onSuccess(String transportName) { 2907 mTransportManager.selectTransport(transportName); 2908 Settings.Secure.putString(mContext.getContentResolver(), 2909 Settings.Secure.BACKUP_TRANSPORT, 2910 mTransportManager.getCurrentTransportName()); 2911 Slog.v(TAG, "Transport successfully selected: " + transport.flattenToShortString()); 2912 try { 2913 listener.onSuccess(transportName); 2914 } catch (RemoteException e) { 2915 // Nothing to do here. 2916 } 2917 } 2918 2919 @Override 2920 public void onFailure(int reason) { 2921 Slog.v(TAG, "Failed to select transport: " + transport.flattenToShortString()); 2922 try { 2923 listener.onFailure(reason); 2924 } catch (RemoteException e) { 2925 // Nothing to do here. 2926 } 2927 } 2928 }); 2929 2930 Binder.restoreCallingIdentity(oldId); 2931 } 2932 2933 // Supply the configuration Intent for the given transport. If the name is not one 2934 // of the available transports, or if the transport does not supply any configuration 2935 // UI, the method returns null. 2936 @Override 2937 public Intent getConfigurationIntent(String transportName) { 2938 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2939 "getConfigurationIntent"); 2940 2941 final IBackupTransport transport = mTransportManager.getTransportBinder(transportName); 2942 if (transport != null) { 2943 try { 2944 final Intent intent = transport.configurationIntent(); 2945 if (MORE_DEBUG) { 2946 Slog.d(TAG, "getConfigurationIntent() returning config intent " 2947 + intent); 2948 } 2949 return intent; 2950 } catch (Exception e) { 2951 /* fall through to return null */ 2952 Slog.e(TAG, "Unable to get configuration intent from transport: " + e.getMessage()); 2953 } 2954 } 2955 2956 return null; 2957 } 2958 2959 // Supply the configuration summary string for the given transport. If the name is 2960 // not one of the available transports, or if the transport does not supply any 2961 // summary / destination string, the method can return null. 2962 // 2963 // This string is used VERBATIM as the summary text of the relevant Settings item! 2964 @Override 2965 public String getDestinationString(String transportName) { 2966 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2967 "getDestinationString"); 2968 2969 final IBackupTransport transport = mTransportManager.getTransportBinder(transportName); 2970 if (transport != null) { 2971 try { 2972 final String text = transport.currentDestinationString(); 2973 if (MORE_DEBUG) Slog.d(TAG, "getDestinationString() returning " + text); 2974 return text; 2975 } catch (Exception e) { 2976 /* fall through to return null */ 2977 Slog.e(TAG, "Unable to get string from transport: " + e.getMessage()); 2978 } 2979 } 2980 2981 return null; 2982 } 2983 2984 // Supply the manage-data intent for the given transport. 2985 @Override 2986 public Intent getDataManagementIntent(String transportName) { 2987 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2988 "getDataManagementIntent"); 2989 2990 final IBackupTransport transport = mTransportManager.getTransportBinder(transportName); 2991 if (transport != null) { 2992 try { 2993 final Intent intent = transport.dataManagementIntent(); 2994 if (MORE_DEBUG) { 2995 Slog.d(TAG, "getDataManagementIntent() returning intent " 2996 + intent); 2997 } 2998 return intent; 2999 } catch (Exception e) { 3000 /* fall through to return null */ 3001 Slog.e(TAG, "Unable to get management intent from transport: " + e.getMessage()); 3002 } 3003 } 3004 3005 return null; 3006 } 3007 3008 // Supply the menu label for affordances that fire the manage-data intent 3009 // for the given transport. 3010 @Override 3011 public String getDataManagementLabel(String transportName) { 3012 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3013 "getDataManagementLabel"); 3014 3015 final IBackupTransport transport = mTransportManager.getTransportBinder(transportName); 3016 if (transport != null) { 3017 try { 3018 final String text = transport.dataManagementLabel(); 3019 if (MORE_DEBUG) Slog.d(TAG, "getDataManagementLabel() returning " + text); 3020 return text; 3021 } catch (Exception e) { 3022 /* fall through to return null */ 3023 Slog.e(TAG, "Unable to get management label from transport: " + e.getMessage()); 3024 } 3025 } 3026 3027 return null; 3028 } 3029 3030 // Callback: a requested backup agent has been instantiated. This should only 3031 // be called from the Activity Manager. 3032 @Override 3033 public void agentConnected(String packageName, IBinder agentBinder) { 3034 synchronized (mAgentConnectLock) { 3035 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 3036 Slog.d(TAG, "agentConnected pkg=" + packageName + " agent=" + agentBinder); 3037 IBackupAgent agent = IBackupAgent.Stub.asInterface(agentBinder); 3038 mConnectedAgent = agent; 3039 mConnecting = false; 3040 } else { 3041 Slog.w(TAG, "Non-system process uid=" + Binder.getCallingUid() 3042 + " claiming agent connected"); 3043 } 3044 mAgentConnectLock.notifyAll(); 3045 } 3046 } 3047 3048 // Callback: a backup agent has failed to come up, or has unexpectedly quit. 3049 // If the agent failed to come up in the first place, the agentBinder argument 3050 // will be null. This should only be called from the Activity Manager. 3051 @Override 3052 public void agentDisconnected(String packageName) { 3053 // TODO: handle backup being interrupted 3054 synchronized (mAgentConnectLock) { 3055 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 3056 mConnectedAgent = null; 3057 mConnecting = false; 3058 } else { 3059 Slog.w(TAG, "Non-system process uid=" + Binder.getCallingUid() 3060 + " claiming agent disconnected"); 3061 } 3062 mAgentConnectLock.notifyAll(); 3063 } 3064 } 3065 3066 // An application being installed will need a restore pass, then the Package Manager 3067 // will need to be told when the restore is finished. 3068 @Override 3069 public void restoreAtInstall(String packageName, int token) { 3070 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 3071 Slog.w(TAG, "Non-system process uid=" + Binder.getCallingUid() 3072 + " attemping install-time restore"); 3073 return; 3074 } 3075 3076 boolean skip = false; 3077 3078 long restoreSet = getAvailableRestoreToken(packageName); 3079 if (DEBUG) { 3080 Slog.v(TAG, "restoreAtInstall pkg=" + packageName 3081 + " token=" + Integer.toHexString(token) 3082 + " restoreSet=" + Long.toHexString(restoreSet)); 3083 } 3084 if (restoreSet == 0) { 3085 if (MORE_DEBUG) Slog.i(TAG, "No restore set"); 3086 skip = true; 3087 } 3088 3089 // Do we have a transport to fetch data for us? 3090 IBackupTransport transport = mTransportManager.getCurrentTransportBinder(); 3091 if (transport == null) { 3092 if (DEBUG) Slog.w(TAG, "No transport"); 3093 skip = true; 3094 } 3095 3096 if (!mAutoRestore) { 3097 if (DEBUG) { 3098 Slog.w(TAG, "Non-restorable state: auto=" + mAutoRestore); 3099 } 3100 skip = true; 3101 } 3102 3103 if (!skip) { 3104 try { 3105 // okay, we're going to attempt a restore of this package from this restore set. 3106 // The eventual message back into the Package Manager to run the post-install 3107 // steps for 'token' will be issued from the restore handling code. 3108 3109 // This can throw and so *must* happen before the wakelock is acquired 3110 String dirName = transport.transportDirName(); 3111 3112 mWakelock.acquire(); 3113 if (MORE_DEBUG) { 3114 Slog.d(TAG, "Restore at install of " + packageName); 3115 } 3116 Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); 3117 msg.obj = new RestoreParams(transport, dirName, null, null, 3118 restoreSet, packageName, token); 3119 mBackupHandler.sendMessage(msg); 3120 } catch (Exception e) { 3121 // Calling into the transport broke; back off and proceed with the installation. 3122 Slog.e(TAG, "Unable to contact transport: " + e.getMessage()); 3123 skip = true; 3124 } 3125 } 3126 3127 if (skip) { 3128 // Auto-restore disabled or no way to attempt a restore; just tell the Package 3129 // Manager to proceed with the post-install handling for this package. 3130 if (DEBUG) Slog.v(TAG, "Finishing install immediately"); 3131 try { 3132 mPackageManagerBinder.finishPackageInstall(token, false); 3133 } catch (RemoteException e) { /* can't happen */ } 3134 } 3135 } 3136 3137 // Hand off a restore session 3138 @Override 3139 public IRestoreSession beginRestoreSession(String packageName, String transport) { 3140 if (DEBUG) { 3141 Slog.v(TAG, "beginRestoreSession: pkg=" + packageName 3142 + " transport=" + transport); 3143 } 3144 3145 boolean needPermission = true; 3146 if (transport == null) { 3147 transport = mTransportManager.getCurrentTransportName(); 3148 3149 if (packageName != null) { 3150 PackageInfo app = null; 3151 try { 3152 app = mPackageManager.getPackageInfo(packageName, 0); 3153 } catch (NameNotFoundException nnf) { 3154 Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName); 3155 throw new IllegalArgumentException("Package " + packageName + " not found"); 3156 } 3157 3158 if (app.applicationInfo.uid == Binder.getCallingUid()) { 3159 // So: using the current active transport, and the caller has asked 3160 // that its own package will be restored. In this narrow use case 3161 // we do not require the caller to hold the permission. 3162 needPermission = false; 3163 } 3164 } 3165 } 3166 3167 if (needPermission) { 3168 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3169 "beginRestoreSession"); 3170 } else { 3171 if (DEBUG) Slog.d(TAG, "restoring self on current transport; no permission needed"); 3172 } 3173 3174 synchronized (this) { 3175 if (mActiveRestoreSession != null) { 3176 Slog.i(TAG, "Restore session requested but one already active"); 3177 return null; 3178 } 3179 if (mBackupRunning) { 3180 Slog.i(TAG, "Restore session requested but currently running backups"); 3181 return null; 3182 } 3183 mActiveRestoreSession = new ActiveRestoreSession(this, packageName, transport); 3184 mBackupHandler.sendEmptyMessageDelayed(MSG_RESTORE_SESSION_TIMEOUT, 3185 TIMEOUT_RESTORE_INTERVAL); 3186 } 3187 return mActiveRestoreSession; 3188 } 3189 3190 public void clearRestoreSession(ActiveRestoreSession currentSession) { 3191 synchronized (this) { 3192 if (currentSession != mActiveRestoreSession) { 3193 Slog.e(TAG, "ending non-current restore session"); 3194 } else { 3195 if (DEBUG) Slog.v(TAG, "Clearing restore session and halting timeout"); 3196 mActiveRestoreSession = null; 3197 mBackupHandler.removeMessages(MSG_RESTORE_SESSION_TIMEOUT); 3198 } 3199 } 3200 } 3201 3202 // Note that a currently-active backup agent has notified us that it has 3203 // completed the given outstanding asynchronous backup/restore operation. 3204 @Override 3205 public void opComplete(int token, long result) { 3206 if (MORE_DEBUG) { 3207 Slog.v(TAG, "opComplete: " + Integer.toHexString(token) + " result=" + result); 3208 } 3209 Operation op = null; 3210 synchronized (mCurrentOpLock) { 3211 op = mCurrentOperations.get(token); 3212 if (op != null) { 3213 if (op.state == OP_TIMEOUT) { 3214 // The operation already timed out, and this is a late response. Tidy up 3215 // and ignore it; we've already dealt with the timeout. 3216 op = null; 3217 mCurrentOperations.delete(token); 3218 } else if (op.state == OP_ACKNOWLEDGED) { 3219 if (DEBUG) { 3220 Slog.w(TAG, "Received duplicate ack for token=" + 3221 Integer.toHexString(token)); 3222 } 3223 op = null; 3224 mCurrentOperations.remove(token); 3225 } else if (op.state == OP_PENDING) { 3226 // Can't delete op from mCurrentOperations. waitUntilOperationComplete can be 3227 // called after we we receive this call. 3228 op.state = OP_ACKNOWLEDGED; 3229 } 3230 } 3231 mCurrentOpLock.notifyAll(); 3232 } 3233 3234 // The completion callback, if any, is invoked on the handler 3235 if (op != null && op.callback != null) { 3236 Pair<BackupRestoreTask, Long> callbackAndResult = Pair.create(op.callback, result); 3237 Message msg = mBackupHandler.obtainMessage(MSG_OP_COMPLETE, callbackAndResult); 3238 mBackupHandler.sendMessage(msg); 3239 } 3240 } 3241 3242 // We also avoid backups of 'disabled' apps 3243 private static boolean appIsDisabled(ApplicationInfo app, PackageManager pm) { 3244 switch (pm.getApplicationEnabledSetting(app.packageName)) { 3245 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: 3246 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: 3247 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: 3248 return true; 3249 3250 default: 3251 return false; 3252 } 3253 } 3254 3255 @Override 3256 public boolean isAppEligibleForBackup(String packageName) { 3257 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3258 "isAppEligibleForBackup"); 3259 try { 3260 PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, 3261 PackageManager.GET_SIGNATURES); 3262 if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo) || 3263 AppBackupUtils.appIsStopped(packageInfo.applicationInfo) || 3264 appIsDisabled(packageInfo.applicationInfo, mPackageManager)) { 3265 return false; 3266 } 3267 IBackupTransport transport = mTransportManager.getCurrentTransportBinder(); 3268 if (transport != null) { 3269 try { 3270 return transport.isAppEligibleForBackup(packageInfo, 3271 AppBackupUtils.appGetsFullBackup(packageInfo)); 3272 } catch (Exception e) { 3273 Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage()); 3274 } 3275 } 3276 // If transport is not present we couldn't tell that the package is not eligible. 3277 return true; 3278 } catch (NameNotFoundException e) { 3279 return false; 3280 } 3281 } 3282 3283 @Override 3284 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3285 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; 3286 3287 long identityToken = Binder.clearCallingIdentity(); 3288 try { 3289 if (args != null) { 3290 for (String arg : args) { 3291 if ("-h".equals(arg)) { 3292 pw.println("'dumpsys backup' optional arguments:"); 3293 pw.println(" -h : this help text"); 3294 pw.println(" a[gents] : dump information about defined backup agents"); 3295 return; 3296 } else if ("agents".startsWith(arg)) { 3297 dumpAgents(pw); 3298 return; 3299 } 3300 } 3301 } 3302 dumpInternal(pw); 3303 } finally { 3304 Binder.restoreCallingIdentity(identityToken); 3305 } 3306 } 3307 3308 private void dumpAgents(PrintWriter pw) { 3309 List<PackageInfo> agentPackages = allAgentPackages(); 3310 pw.println("Defined backup agents:"); 3311 for (PackageInfo pkg : agentPackages) { 3312 pw.print(" "); 3313 pw.print(pkg.packageName); 3314 pw.println(':'); 3315 pw.print(" "); 3316 pw.println(pkg.applicationInfo.backupAgentName); 3317 } 3318 } 3319 3320 private void dumpInternal(PrintWriter pw) { 3321 synchronized (mQueueLock) { 3322 pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled") 3323 + " / " + (!mProvisioned ? "not " : "") + "provisioned / " 3324 + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init"); 3325 pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled")); 3326 if (mBackupRunning) pw.println("Backup currently running"); 3327 pw.println("Last backup pass started: " + mLastBackupPass 3328 + " (now = " + System.currentTimeMillis() + ')'); 3329 pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled()); 3330 3331 pw.println("Transport whitelist:"); 3332 for (ComponentName transport : mTransportManager.getTransportWhitelist()) { 3333 pw.print(" "); 3334 pw.println(transport.flattenToShortString()); 3335 } 3336 3337 pw.println("Available transports:"); 3338 final String[] transports = listAllTransports(); 3339 if (transports != null) { 3340 for (String t : listAllTransports()) { 3341 pw.println((t.equals(mTransportManager.getCurrentTransportName()) ? " * " 3342 : " ") + t); 3343 try { 3344 IBackupTransport transport = mTransportManager.getTransportBinder(t); 3345 File dir = new File(mBaseStateDir, transport.transportDirName()); 3346 pw.println(" destination: " + transport.currentDestinationString()); 3347 pw.println(" intent: " + transport.configurationIntent()); 3348 for (File f : dir.listFiles()) { 3349 pw.println( 3350 " " + f.getName() + " - " + f.length() + " state bytes"); 3351 } 3352 } catch (Exception e) { 3353 Slog.e(TAG, "Error in transport", e); 3354 pw.println(" Error: " + e); 3355 } 3356 } 3357 } 3358 3359 pw.println("Pending init: " + mPendingInits.size()); 3360 for (String s : mPendingInits) { 3361 pw.println(" " + s); 3362 } 3363 3364 if (DEBUG_BACKUP_TRACE) { 3365 synchronized (mBackupTrace) { 3366 if (!mBackupTrace.isEmpty()) { 3367 pw.println("Most recent backup trace:"); 3368 for (String s : mBackupTrace) { 3369 pw.println(" " + s); 3370 } 3371 } 3372 } 3373 } 3374 3375 pw.print("Ancestral: "); 3376 pw.println(Long.toHexString(mAncestralToken)); 3377 pw.print("Current: "); 3378 pw.println(Long.toHexString(mCurrentToken)); 3379 3380 int N = mBackupParticipants.size(); 3381 pw.println("Participants:"); 3382 for (int i = 0; i < N; i++) { 3383 int uid = mBackupParticipants.keyAt(i); 3384 pw.print(" uid: "); 3385 pw.println(uid); 3386 HashSet<String> participants = mBackupParticipants.valueAt(i); 3387 for (String app : participants) { 3388 pw.println(" " + app); 3389 } 3390 } 3391 3392 pw.println("Ancestral packages: " 3393 + (mAncestralPackages == null ? "none" : mAncestralPackages.size())); 3394 if (mAncestralPackages != null) { 3395 for (String pkg : mAncestralPackages) { 3396 pw.println(" " + pkg); 3397 } 3398 } 3399 3400 pw.println("Ever backed up: " + mEverStoredApps.size()); 3401 for (String pkg : mEverStoredApps) { 3402 pw.println(" " + pkg); 3403 } 3404 3405 pw.println("Pending key/value backup: " + mPendingBackups.size()); 3406 for (BackupRequest req : mPendingBackups.values()) { 3407 pw.println(" " + req); 3408 } 3409 3410 pw.println("Full backup queue:" + mFullBackupQueue.size()); 3411 for (FullBackupEntry entry : mFullBackupQueue) { 3412 pw.print(" "); 3413 pw.print(entry.lastBackup); 3414 pw.print(" : "); 3415 pw.println(entry.packageName); 3416 } 3417 } 3418 } 3419 3420 3421 @Override 3422 public IBackupManager getBackupManagerBinder() { 3423 return mBackupManagerBinder; 3424 } 3425 3426} 3427