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 17 package com.android.server.backup; 18 19 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND; 20 21 import static com.android.server.backup.BackupManagerService.DEBUG; 22 import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING; 23 import static com.android.server.backup.BackupManagerService.MORE_DEBUG; 24 import static com.android.server.backup.BackupManagerService.TAG; 25 import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT; 26 import static com.android.server.backup.internal.BackupHandler.MSG_FULL_CONFIRMATION_TIMEOUT; 27 import static com.android.server.backup.internal.BackupHandler.MSG_OP_COMPLETE; 28 import static com.android.server.backup.internal.BackupHandler.MSG_REQUEST_BACKUP; 29 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT; 30 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT; 31 import static com.android.server.backup.internal.BackupHandler.MSG_RETRY_CLEAR; 32 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_BACKUP; 33 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_RESTORE; 34 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_BACKUP; 35 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_CLEAR; 36 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE; 37 import static com.android.server.backup.internal.BackupHandler.MSG_SCHEDULE_BACKUP_PACKAGE; 38 39 import android.annotation.Nullable; 40 import android.annotation.UserIdInt; 41 import android.app.ActivityManager; 42 import android.app.ActivityManagerInternal; 43 import android.app.AlarmManager; 44 import android.app.AppGlobals; 45 import android.app.IActivityManager; 46 import android.app.IBackupAgent; 47 import android.app.PendingIntent; 48 import android.app.backup.BackupAgent; 49 import android.app.backup.BackupManager; 50 import android.app.backup.BackupManager.OperationType; 51 import android.app.backup.BackupManagerMonitor; 52 import android.app.backup.FullBackup; 53 import android.app.backup.IBackupManager; 54 import android.app.backup.IBackupManagerMonitor; 55 import android.app.backup.IBackupObserver; 56 import android.app.backup.IFullBackupRestoreObserver; 57 import android.app.backup.IRestoreSession; 58 import android.app.backup.ISelectBackupTransportCallback; 59 import android.content.ActivityNotFoundException; 60 import android.content.BroadcastReceiver; 61 import android.content.ComponentName; 62 import android.content.ContentResolver; 63 import android.content.Context; 64 import android.content.Intent; 65 import android.content.IntentFilter; 66 import android.content.pm.ApplicationInfo; 67 import android.content.pm.IPackageManager; 68 import android.content.pm.PackageInfo; 69 import android.content.pm.PackageManager; 70 import android.content.pm.PackageManager.NameNotFoundException; 71 import android.content.pm.PackageManagerInternal; 72 import android.database.ContentObserver; 73 import android.net.Uri; 74 import android.os.Binder; 75 import android.os.Build; 76 import android.os.Bundle; 77 import android.os.Handler; 78 import android.os.HandlerThread; 79 import android.os.IBinder; 80 import android.os.Message; 81 import android.os.ParcelFileDescriptor; 82 import android.os.PowerManager; 83 import android.os.PowerManager.ServiceType; 84 import android.os.PowerSaveState; 85 import android.os.Process; 86 import android.os.RemoteException; 87 import android.os.SELinux; 88 import android.os.ServiceManager; 89 import android.os.SystemClock; 90 import android.os.UserHandle; 91 import android.os.WorkSource; 92 import android.os.storage.IStorageManager; 93 import android.os.storage.StorageManager; 94 import android.provider.Settings; 95 import android.text.TextUtils; 96 import android.util.ArraySet; 97 import android.util.AtomicFile; 98 import android.util.EventLog; 99 import android.util.FeatureFlagUtils; 100 import android.util.Pair; 101 import android.util.Slog; 102 import android.util.SparseArray; 103 104 import com.android.internal.annotations.GuardedBy; 105 import com.android.internal.annotations.VisibleForTesting; 106 import com.android.internal.backup.IBackupTransport; 107 import com.android.internal.util.Preconditions; 108 import com.android.server.AppWidgetBackupBridge; 109 import com.android.server.EventLogTags; 110 import com.android.server.LocalServices; 111 import com.android.server.backup.fullbackup.FullBackupEntry; 112 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask; 113 import com.android.server.backup.internal.BackupHandler; 114 import com.android.server.backup.internal.ClearDataObserver; 115 import com.android.server.backup.internal.OnTaskFinishedListener; 116 import com.android.server.backup.internal.Operation; 117 import com.android.server.backup.internal.PerformInitializeTask; 118 import com.android.server.backup.internal.RunInitializeReceiver; 119 import com.android.server.backup.internal.SetupObserver; 120 import com.android.server.backup.keyvalue.BackupRequest; 121 import com.android.server.backup.params.AdbBackupParams; 122 import com.android.server.backup.params.AdbParams; 123 import com.android.server.backup.params.AdbRestoreParams; 124 import com.android.server.backup.params.BackupParams; 125 import com.android.server.backup.params.ClearParams; 126 import com.android.server.backup.params.ClearRetryParams; 127 import com.android.server.backup.params.RestoreParams; 128 import com.android.server.backup.restore.ActiveRestoreSession; 129 import com.android.server.backup.restore.PerformUnifiedRestoreTask; 130 import com.android.server.backup.transport.TransportClient; 131 import com.android.server.backup.transport.TransportNotAvailableException; 132 import com.android.server.backup.transport.TransportNotRegisteredException; 133 import com.android.server.backup.utils.BackupEligibilityRules; 134 import com.android.server.backup.utils.BackupManagerMonitorUtils; 135 import com.android.server.backup.utils.BackupObserverUtils; 136 import com.android.server.backup.utils.SparseArrayUtils; 137 138 import com.google.android.collect.Sets; 139 140 import java.io.BufferedInputStream; 141 import java.io.ByteArrayOutputStream; 142 import java.io.DataInputStream; 143 import java.io.DataOutputStream; 144 import java.io.File; 145 import java.io.FileDescriptor; 146 import java.io.FileInputStream; 147 import java.io.FileNotFoundException; 148 import java.io.FileOutputStream; 149 import java.io.IOException; 150 import java.io.PrintWriter; 151 import java.io.RandomAccessFile; 152 import java.security.SecureRandom; 153 import java.text.SimpleDateFormat; 154 import java.util.ArrayDeque; 155 import java.util.ArrayList; 156 import java.util.Arrays; 157 import java.util.Collections; 158 import java.util.Date; 159 import java.util.HashMap; 160 import java.util.HashSet; 161 import java.util.LinkedHashSet; 162 import java.util.LinkedList; 163 import java.util.List; 164 import java.util.Objects; 165 import java.util.Queue; 166 import java.util.Random; 167 import java.util.Set; 168 import java.util.concurrent.CountDownLatch; 169 import java.util.concurrent.atomic.AtomicInteger; 170 171 /** System service that performs backup/restore operations. */ 172 public class UserBackupManagerService { 173 /** 174 * Wrapper over {@link PowerManager.WakeLock} to prevent double-free exceptions on release() 175 * after quit(). 176 */ 177 public static class BackupWakeLock { 178 private final PowerManager.WakeLock mPowerManagerWakeLock; 179 private boolean mHasQuit = false; 180 private int mUserId; 181 BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock, int userId)182 public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock, int userId) { 183 mPowerManagerWakeLock = powerManagerWakeLock; 184 mUserId = userId; 185 } 186 187 /** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */ acquire()188 public synchronized void acquire() { 189 if (mHasQuit) { 190 Slog.v( 191 TAG, 192 addUserIdToLogMessage( 193 mUserId, 194 "Ignore wakelock acquire after quit: " 195 + mPowerManagerWakeLock.getTag())); 196 return; 197 } 198 mPowerManagerWakeLock.acquire(); 199 Slog.v( 200 TAG, 201 addUserIdToLogMessage( 202 mUserId, "Acquired wakelock:" + mPowerManagerWakeLock.getTag())); 203 } 204 205 /** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */ release()206 public synchronized void release() { 207 if (mHasQuit) { 208 Slog.v( 209 TAG, 210 addUserIdToLogMessage( 211 mUserId, 212 "Ignore wakelock release after quit: " 213 + mPowerManagerWakeLock.getTag())); 214 return; 215 } 216 mPowerManagerWakeLock.release(); 217 Slog.v( 218 TAG, 219 addUserIdToLogMessage( 220 mUserId, "Released wakelock:" + mPowerManagerWakeLock.getTag())); 221 } 222 223 /** 224 * Returns true if the {@link PowerManager.WakeLock} has been acquired but not yet released. 225 */ isHeld()226 public synchronized boolean isHeld() { 227 return mPowerManagerWakeLock.isHeld(); 228 } 229 230 /** Release the {@link PowerManager.WakeLock} till it isn't held. */ quit()231 public synchronized void quit() { 232 while (mPowerManagerWakeLock.isHeld()) { 233 Slog.v( 234 TAG, 235 addUserIdToLogMessage( 236 mUserId, "Releasing wakelock: " + mPowerManagerWakeLock.getTag())); 237 mPowerManagerWakeLock.release(); 238 } 239 mHasQuit = true; 240 } 241 } 242 243 // Persistently track the need to do a full init. 244 private static final String INIT_SENTINEL_FILE_NAME = "_need_init_"; 245 246 // System-private key used for backing up an app's widget state. Must 247 // begin with U+FFxx by convention (we reserve all keys starting 248 // with U+FF00 or higher for system use). 249 public static final String KEY_WIDGET_STATE = "\uffed\uffedwidget"; 250 251 // Name and current contents version of the full-backup manifest file 252 // 253 // Manifest version history: 254 // 255 // 1 : initial release 256 public static final String BACKUP_MANIFEST_FILENAME = "_manifest"; 257 public static final int BACKUP_MANIFEST_VERSION = 1; 258 259 // External archive format version history: 260 // 261 // 1 : initial release 262 // 2 : no format change per se; version bump to facilitate PBKDF2 version skew detection 263 // 3 : introduced "_meta" metadata file; no other format change per se 264 // 4 : added support for new device-encrypted storage locations 265 // 5 : added support for key-value packages 266 public static final int BACKUP_FILE_VERSION = 5; 267 public static final String BACKUP_FILE_HEADER_MAGIC = "ANDROID BACKUP\n"; 268 public static final String BACKUP_METADATA_FILENAME = "_meta"; 269 public static final int BACKUP_METADATA_VERSION = 1; 270 public static final int BACKUP_WIDGET_METADATA_TOKEN = 0x01FFED01; 271 272 private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1; 273 274 // Round-robin queue for scheduling full backup passes. 275 private static final int SCHEDULE_FILE_VERSION = 1; 276 277 public static final String SETTINGS_PACKAGE = "com.android.providers.settings"; 278 public static final String SHARED_BACKUP_AGENT_PACKAGE = "com.android.sharedstoragebackup"; 279 280 // Pseudoname that we use for the Package Manager metadata "package". 281 public static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; 282 283 // Retry interval for clear/init when the transport is unavailable 284 private static final long TRANSPORT_RETRY_INTERVAL = 1 * AlarmManager.INTERVAL_HOUR; 285 286 public static final String RUN_INITIALIZE_ACTION = "android.app.backup.intent.INIT"; 287 private static final String BACKUP_FINISHED_ACTION = "android.intent.action.BACKUP_FINISHED"; 288 private static final String BACKUP_FINISHED_PACKAGE_EXTRA = "packageName"; 289 290 // Bookkeeping of in-flight operations. The operation token is the index of the entry in the 291 // pending operations list. 292 public static final int OP_PENDING = 0; 293 private static final int OP_ACKNOWLEDGED = 1; 294 private static final int OP_TIMEOUT = -1; 295 296 // Waiting for backup agent to respond during backup operation. 297 public static final int OP_TYPE_BACKUP_WAIT = 0; 298 299 // Waiting for backup agent to respond during restore operation. 300 public static final int OP_TYPE_RESTORE_WAIT = 1; 301 302 // An entire backup operation spanning multiple packages. 303 public static final int OP_TYPE_BACKUP = 2; 304 305 // Time delay for initialization operations that can be delayed so as not to consume too much 306 // CPU on bring-up and increase time-to-UI. 307 private static final long INITIALIZATION_DELAY_MILLIS = 3000; 308 309 // Timeout interval for deciding that a bind has taken too long. 310 private static final long BIND_TIMEOUT_INTERVAL = 10 * 1000; 311 // Timeout interval for deciding that a clear-data has taken too long. 312 private static final long CLEAR_DATA_TIMEOUT_INTERVAL = 30 * 1000; 313 314 // User confirmation timeout for a full backup/restore operation. It's this long in 315 // order to give them time to enter the backup password. 316 private static final long TIMEOUT_FULL_CONFIRMATION = 60 * 1000; 317 318 // If an app is busy when we want to do a full-data backup, how long to defer the retry. 319 // This is fuzzed, so there are two parameters; backoff_min + Rand[0, backoff_fuzz) 320 private static final long BUSY_BACKOFF_MIN_MILLIS = 1000 * 60 * 60; // one hour 321 private static final int BUSY_BACKOFF_FUZZ = 1000 * 60 * 60 * 2; // two hours 322 323 private static final String SERIAL_ID_FILE = "serial_id"; 324 325 private static final String SKIP_USER_FACING_PACKAGES = "backup_skip_user_facing_packages"; 326 private static final String WALLPAPER_PACKAGE = "com.android.wallpaperbackup"; 327 328 private final @UserIdInt int mUserId; 329 private final BackupAgentTimeoutParameters mAgentTimeoutParameters; 330 private final TransportManager mTransportManager; 331 332 private final Context mContext; 333 private final PackageManager mPackageManager; 334 private final IPackageManager mPackageManagerBinder; 335 private final IActivityManager mActivityManager; 336 private final ActivityManagerInternal mActivityManagerInternal; 337 private PowerManager mPowerManager; 338 private final AlarmManager mAlarmManager; 339 private final IStorageManager mStorageManager; 340 private final BackupManagerConstants mConstants; 341 private final BackupWakeLock mWakelock; 342 private final BackupHandler mBackupHandler; 343 private final BackupEligibilityRules mScheduledBackupEligibility; 344 345 private final IBackupManager mBackupManagerBinder; 346 347 private boolean mEnabled; // writes to this are synchronized on 'this' 348 private boolean mSetupComplete; 349 private boolean mAutoRestore; 350 351 private final PendingIntent mRunInitIntent; 352 353 private final ArraySet<String> mPendingInits = new ArraySet<>(); // transport names 354 355 // map UIDs to the set of participating packages under that UID 356 private final SparseArray<HashSet<String>> mBackupParticipants = new SparseArray<>(); 357 358 // Backups that we haven't started yet. Keys are package names. 359 private final HashMap<String, BackupRequest> mPendingBackups = new HashMap<>(); 360 361 // locking around the pending-backup management 362 private final Object mQueueLock = new Object(); 363 364 private final UserBackupPreferences mBackupPreferences; 365 366 // The thread performing the sequence of queued backups binds to each app's agent 367 // in succession. Bind notifications are asynchronously delivered through the 368 // Activity Manager; use this lock object to signal when a requested binding has 369 // completed. 370 private final Object mAgentConnectLock = new Object(); 371 private IBackupAgent mConnectedAgent; 372 private volatile boolean mConnecting; 373 374 private volatile boolean mBackupRunning; 375 private volatile long mLastBackupPass; 376 377 // A similar synchronization mechanism around clearing apps' data for restore 378 private final Object mClearDataLock = new Object(); 379 private volatile boolean mClearingData; 380 381 // Used by ADB. 382 private final BackupPasswordManager mBackupPasswordManager; 383 private final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<>(); 384 private final SecureRandom mRng = new SecureRandom(); 385 386 // Time when we post the transport registration operation 387 private final long mRegisterTransportsRequestedTime; 388 389 @GuardedBy("mQueueLock") 390 private PerformFullTransportBackupTask mRunningFullBackupTask; 391 392 @GuardedBy("mQueueLock") 393 private ArrayList<FullBackupEntry> mFullBackupQueue; 394 395 @GuardedBy("mPendingRestores") 396 private boolean mIsRestoreInProgress; 397 398 @GuardedBy("mPendingRestores") 399 private final Queue<PerformUnifiedRestoreTask> mPendingRestores = new ArrayDeque<>(); 400 401 private ActiveRestoreSession mActiveRestoreSession; 402 403 /** 404 * mCurrentOperations contains the list of currently active operations. 405 * 406 * If type of operation is OP_TYPE_WAIT, it are waiting for an ack or timeout. 407 * An operation wraps a BackupRestoreTask within it. 408 * It's the responsibility of this task to remove the operation from this array. 409 * 410 * A BackupRestore task gets notified of ack/timeout for the operation via 411 * BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called 412 * on the mCurrentOpLock. 413 * {@link UserBackupManagerService#waitUntilOperationComplete(int)} is 414 * used in various places to 'wait' for notifyAll and detect change of pending state of an 415 * operation. So typically, an operation will be removed from this array by: 416 * - BackupRestoreTask#handleCancel and 417 * - BackupRestoreTask#operationComplete OR waitUntilOperationComplete. Do not remove at both 418 * these places because waitUntilOperationComplete relies on the operation being present to 419 * determine its completion status. 420 * 421 * If type of operation is OP_BACKUP, it is a task running backups. It provides a handle to 422 * cancel backup tasks. 423 */ 424 @GuardedBy("mCurrentOpLock") 425 private final SparseArray<Operation> mCurrentOperations = new SparseArray<>(); 426 private final Object mCurrentOpLock = new Object(); 427 private final Random mTokenGenerator = new Random(); 428 private final AtomicInteger mNextToken = new AtomicInteger(); 429 430 // Where we keep our journal files and other bookkeeping. 431 private final File mBaseStateDir; 432 private final File mDataDir; 433 private final File mJournalDir; 434 @Nullable 435 private DataChangedJournal mJournal; 436 private final File mFullBackupScheduleFile; 437 438 // Keep a log of all the apps we've ever backed up. 439 private ProcessedPackagesJournal mProcessedPackagesJournal; 440 441 private File mTokenFile; 442 private Set<String> mAncestralPackages = null; 443 private long mAncestralToken = 0; 444 private long mCurrentToken = 0; 445 @Nullable private File mAncestralSerialNumberFile; 446 @OperationType private volatile long mAncestralOperationType; 447 448 private final ContentObserver mSetupObserver; 449 private final BroadcastReceiver mRunInitReceiver; 450 451 /** 452 * Creates an instance of {@link UserBackupManagerService} and initializes state for it. This 453 * includes setting up the directories where we keep our bookkeeping and transport management. 454 * 455 * @see #createAndInitializeService(int, Context, BackupManagerService, HandlerThread, File, 456 * File, TransportManager) 457 */ createAndInitializeService( @serIdInt int userId, Context context, BackupManagerService backupManagerService, Set<ComponentName> transportWhitelist)458 static UserBackupManagerService createAndInitializeService( 459 @UserIdInt int userId, 460 Context context, 461 BackupManagerService backupManagerService, 462 Set<ComponentName> transportWhitelist) { 463 String currentTransport = 464 Settings.Secure.getStringForUser( 465 context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT, userId); 466 if (TextUtils.isEmpty(currentTransport)) { 467 currentTransport = null; 468 } 469 470 if (DEBUG) { 471 Slog.v( 472 TAG, 473 addUserIdToLogMessage(userId, "Starting with transport " + currentTransport)); 474 } 475 TransportManager transportManager = 476 new TransportManager(userId, context, transportWhitelist, currentTransport); 477 478 File baseStateDir = UserBackupManagerFiles.getBaseStateDir(userId); 479 File dataDir = UserBackupManagerFiles.getDataDir(userId); 480 481 HandlerThread userBackupThread = 482 new HandlerThread("backup-" + userId, Process.THREAD_PRIORITY_BACKGROUND); 483 userBackupThread.start(); 484 if (DEBUG) { 485 Slog.d( 486 TAG, 487 addUserIdToLogMessage(userId, "Started thread " + userBackupThread.getName())); 488 } 489 490 return createAndInitializeService( 491 userId, 492 context, 493 backupManagerService, 494 userBackupThread, 495 baseStateDir, 496 dataDir, 497 transportManager); 498 } 499 500 /** 501 * Creates an instance of {@link UserBackupManagerService}. 502 * 503 * @param userId The user which this service is for. 504 * @param context The system server context. 505 * @param backupManagerService A reference to the proxy to {@link BackupManagerService}. 506 * @param userBackupThread The thread running backup/restore operations for the user. 507 * @param baseStateDir The directory we store the user's persistent bookkeeping data. 508 * @param dataDir The directory we store the user's temporary staging data. 509 * @param transportManager The {@link TransportManager} responsible for handling the user's 510 * transports. 511 */ 512 @VisibleForTesting createAndInitializeService( @serIdInt int userId, Context context, BackupManagerService backupManagerService, HandlerThread userBackupThread, File baseStateDir, File dataDir, TransportManager transportManager)513 public static UserBackupManagerService createAndInitializeService( 514 @UserIdInt int userId, 515 Context context, 516 BackupManagerService backupManagerService, 517 HandlerThread userBackupThread, 518 File baseStateDir, 519 File dataDir, 520 TransportManager transportManager) { 521 return new UserBackupManagerService( 522 userId, 523 context, 524 backupManagerService, 525 userBackupThread, 526 baseStateDir, 527 dataDir, 528 transportManager); 529 } 530 531 /** 532 * Returns the value of {@link Settings.Secure#USER_SETUP_COMPLETE} for the specified user 533 * {@code userId} as a {@code boolean}. 534 */ getSetupCompleteSettingForUser(Context context, int userId)535 public static boolean getSetupCompleteSettingForUser(Context context, int userId) { 536 return Settings.Secure.getIntForUser( 537 context.getContentResolver(), 538 Settings.Secure.USER_SETUP_COMPLETE, 539 0, 540 userId) 541 != 0; 542 } 543 544 @VisibleForTesting UserBackupManagerService(Context context, PackageManager packageManager)545 UserBackupManagerService(Context context, PackageManager packageManager) { 546 mContext = context; 547 548 mUserId = 0; 549 mRegisterTransportsRequestedTime = 0; 550 mPackageManager = packageManager; 551 552 mBaseStateDir = null; 553 mDataDir = null; 554 mJournalDir = null; 555 mFullBackupScheduleFile = null; 556 mSetupObserver = null; 557 mRunInitReceiver = null; 558 mRunInitIntent = null; 559 mAgentTimeoutParameters = null; 560 mTransportManager = null; 561 mActivityManagerInternal = null; 562 mAlarmManager = null; 563 mConstants = null; 564 mWakelock = null; 565 mBackupHandler = null; 566 mBackupPreferences = null; 567 mBackupPasswordManager = null; 568 mPackageManagerBinder = null; 569 mActivityManager = null; 570 mStorageManager = null; 571 mBackupManagerBinder = null; 572 mScheduledBackupEligibility = null; 573 } 574 UserBackupManagerService( @serIdInt int userId, Context context, BackupManagerService parent, HandlerThread userBackupThread, File baseStateDir, File dataDir, TransportManager transportManager)575 private UserBackupManagerService( 576 @UserIdInt int userId, 577 Context context, 578 BackupManagerService parent, 579 HandlerThread userBackupThread, 580 File baseStateDir, 581 File dataDir, 582 TransportManager transportManager) { 583 mUserId = userId; 584 mContext = Objects.requireNonNull(context, "context cannot be null"); 585 mPackageManager = context.getPackageManager(); 586 mPackageManagerBinder = AppGlobals.getPackageManager(); 587 mActivityManager = ActivityManager.getService(); 588 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 589 mScheduledBackupEligibility = getEligibilityRules(mPackageManager, userId, 590 OperationType.BACKUP); 591 592 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 593 mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 594 mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount")); 595 596 Objects.requireNonNull(parent, "parent cannot be null"); 597 mBackupManagerBinder = BackupManagerService.asInterface(parent.asBinder()); 598 599 mAgentTimeoutParameters = new 600 BackupAgentTimeoutParameters(Handler.getMain(), mContext.getContentResolver()); 601 mAgentTimeoutParameters.start(); 602 603 Objects.requireNonNull(userBackupThread, "userBackupThread cannot be null"); 604 mBackupHandler = new BackupHandler(this, userBackupThread); 605 606 // Set up our bookkeeping 607 final ContentResolver resolver = context.getContentResolver(); 608 mSetupComplete = getSetupCompleteSettingForUser(context, userId); 609 mAutoRestore = Settings.Secure.getIntForUser(resolver, 610 Settings.Secure.BACKUP_AUTO_RESTORE, 1, userId) != 0; 611 612 mSetupObserver = new SetupObserver(this, mBackupHandler); 613 resolver.registerContentObserver( 614 Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 615 /* notifyForDescendents */ false, 616 mSetupObserver, 617 mUserId); 618 619 mBaseStateDir = Objects.requireNonNull(baseStateDir, "baseStateDir cannot be null"); 620 // TODO (b/120424138): Remove once the system user is migrated to use the per-user CE 621 // directory. Per-user CE directories are managed by vold. 622 if (userId == UserHandle.USER_SYSTEM) { 623 mBaseStateDir.mkdirs(); 624 if (!SELinux.restorecon(mBaseStateDir)) { 625 Slog.w( 626 TAG, 627 addUserIdToLogMessage( 628 userId, "SELinux restorecon failed on " + mBaseStateDir)); 629 } 630 } 631 632 // TODO (b/120424138): The system user currently uses the cache which is managed by init.rc 633 // Initialization and restorecon is managed by vold for per-user CE directories. 634 mDataDir = Objects.requireNonNull(dataDir, "dataDir cannot be null"); 635 mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng); 636 637 // Receiver for transport initialization. 638 mRunInitReceiver = new RunInitializeReceiver(this); 639 IntentFilter filter = new IntentFilter(); 640 filter.addAction(RUN_INITIALIZE_ACTION); 641 context.registerReceiverAsUser( 642 mRunInitReceiver, 643 UserHandle.of(userId), 644 filter, 645 android.Manifest.permission.BACKUP, 646 /* scheduler */ null); 647 648 Intent initIntent = new Intent(RUN_INITIALIZE_ACTION); 649 initIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 650 mRunInitIntent = 651 PendingIntent.getBroadcastAsUser( 652 context, 653 /* requestCode */ 0, 654 initIntent, 655 /* flags */ PendingIntent.FLAG_IMMUTABLE, 656 UserHandle.of(userId)); 657 658 // Set up the backup-request journaling 659 mJournalDir = new File(mBaseStateDir, "pending"); 660 mJournalDir.mkdirs(); // creates mBaseStateDir along the way 661 mJournal = null; // will be created on first use 662 663 mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver()); 664 // We are observing changes to the constants throughout the lifecycle of BMS. This is 665 // because we reference the constants in multiple areas of BMS, which otherwise would 666 // require frequent starting and stopping. 667 mConstants.start(); 668 669 // Build our mapping of uid to backup client services. This implicitly 670 // schedules a backup pass on the Package Manager metadata the first 671 // time anything needs to be backed up. 672 synchronized (mBackupParticipants) { 673 addPackageParticipantsLocked(null); 674 } 675 676 mTransportManager = 677 Objects.requireNonNull(transportManager, "transportManager cannot be null"); 678 mTransportManager.setOnTransportRegisteredListener(this::onTransportRegistered); 679 mRegisterTransportsRequestedTime = SystemClock.elapsedRealtime(); 680 mBackupHandler.postDelayed( 681 mTransportManager::registerTransports, INITIALIZATION_DELAY_MILLIS); 682 683 // Now that we know about valid backup participants, parse any leftover journal files into 684 // the pending backup set 685 mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS); 686 687 mBackupPreferences = new UserBackupPreferences(mContext, mBaseStateDir); 688 689 // Power management 690 mWakelock = new BackupWakeLock( 691 mPowerManager.newWakeLock( 692 PowerManager.PARTIAL_WAKE_LOCK, 693 "*backup*-" + userId + "-" + userBackupThread.getThreadId()), userId); 694 695 // Set up the various sorts of package tracking we do 696 mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule"); 697 initPackageTracking(); 698 } 699 700 @VisibleForTesting initializeBackupEnableState()701 void initializeBackupEnableState() { 702 boolean isEnabled = readEnabledState(); 703 // Don't persist value to disk since we just read it from there. 704 setBackupEnabled(isEnabled, /* persistToDisk */ false); 705 } 706 707 /** Cleans up state when the user of this service is stopped. */ 708 @VisibleForTesting tearDownService()709 protected void tearDownService() { 710 mAgentTimeoutParameters.stop(); 711 mConstants.stop(); 712 mContext.getContentResolver().unregisterContentObserver(mSetupObserver); 713 mContext.unregisterReceiver(mRunInitReceiver); 714 mContext.unregisterReceiver(mPackageTrackingReceiver); 715 mBackupHandler.stop(); 716 } 717 getUserId()718 public @UserIdInt int getUserId() { 719 return mUserId; 720 } 721 getConstants()722 public BackupManagerConstants getConstants() { 723 return mConstants; 724 } 725 getAgentTimeoutParameters()726 public BackupAgentTimeoutParameters getAgentTimeoutParameters() { 727 return mAgentTimeoutParameters; 728 } 729 getContext()730 public Context getContext() { 731 return mContext; 732 } 733 getPackageManager()734 public PackageManager getPackageManager() { 735 return mPackageManager; 736 } 737 getPackageManagerBinder()738 public IPackageManager getPackageManagerBinder() { 739 return mPackageManagerBinder; 740 } 741 getActivityManager()742 public IActivityManager getActivityManager() { 743 return mActivityManager; 744 } 745 getAlarmManager()746 public AlarmManager getAlarmManager() { 747 return mAlarmManager; 748 } 749 750 @VisibleForTesting setPowerManager(PowerManager powerManager)751 void setPowerManager(PowerManager powerManager) { 752 mPowerManager = powerManager; 753 } 754 getTransportManager()755 public TransportManager getTransportManager() { 756 return mTransportManager; 757 } 758 isEnabled()759 public boolean isEnabled() { 760 return mEnabled; 761 } 762 setEnabled(boolean enabled)763 public void setEnabled(boolean enabled) { 764 mEnabled = enabled; 765 } 766 isSetupComplete()767 public boolean isSetupComplete() { 768 return mSetupComplete; 769 } 770 setSetupComplete(boolean setupComplete)771 public void setSetupComplete(boolean setupComplete) { 772 mSetupComplete = setupComplete; 773 } 774 getWakelock()775 public BackupWakeLock getWakelock() { 776 return mWakelock; 777 } 778 779 /** 780 * Sets the {@link WorkSource} of the {@link PowerManager.WakeLock} returned by {@link 781 * #getWakelock()}. 782 */ 783 @VisibleForTesting setWorkSource(@ullable WorkSource workSource)784 public void setWorkSource(@Nullable WorkSource workSource) { 785 // TODO: This is for testing, unfortunately WakeLock is final and WorkSource is not exposed 786 mWakelock.mPowerManagerWakeLock.setWorkSource(workSource); 787 } 788 getBackupHandler()789 public Handler getBackupHandler() { 790 return mBackupHandler; 791 } 792 getRunInitIntent()793 public PendingIntent getRunInitIntent() { 794 return mRunInitIntent; 795 } 796 getPendingBackups()797 public HashMap<String, BackupRequest> getPendingBackups() { 798 return mPendingBackups; 799 } 800 getQueueLock()801 public Object getQueueLock() { 802 return mQueueLock; 803 } 804 isBackupRunning()805 public boolean isBackupRunning() { 806 return mBackupRunning; 807 } 808 setBackupRunning(boolean backupRunning)809 public void setBackupRunning(boolean backupRunning) { 810 mBackupRunning = backupRunning; 811 } 812 setLastBackupPass(long lastBackupPass)813 public void setLastBackupPass(long lastBackupPass) { 814 mLastBackupPass = lastBackupPass; 815 } 816 getClearDataLock()817 public Object getClearDataLock() { 818 return mClearDataLock; 819 } 820 setClearingData(boolean clearingData)821 public void setClearingData(boolean clearingData) { 822 mClearingData = clearingData; 823 } 824 isRestoreInProgress()825 public boolean isRestoreInProgress() { 826 return mIsRestoreInProgress; 827 } 828 setRestoreInProgress(boolean restoreInProgress)829 public void setRestoreInProgress(boolean restoreInProgress) { 830 mIsRestoreInProgress = restoreInProgress; 831 } 832 getPendingRestores()833 public Queue<PerformUnifiedRestoreTask> getPendingRestores() { 834 return mPendingRestores; 835 } 836 getActiveRestoreSession()837 public ActiveRestoreSession getActiveRestoreSession() { 838 return mActiveRestoreSession; 839 } 840 getCurrentOperations()841 public SparseArray<Operation> getCurrentOperations() { 842 return mCurrentOperations; 843 } 844 getCurrentOpLock()845 public Object getCurrentOpLock() { 846 return mCurrentOpLock; 847 } 848 getAdbBackupRestoreConfirmations()849 public SparseArray<AdbParams> getAdbBackupRestoreConfirmations() { 850 return mAdbBackupRestoreConfirmations; 851 } 852 getBaseStateDir()853 public File getBaseStateDir() { 854 return mBaseStateDir; 855 } 856 getDataDir()857 public File getDataDir() { 858 return mDataDir; 859 } 860 861 @VisibleForTesting getPackageTrackingReceiver()862 BroadcastReceiver getPackageTrackingReceiver() { 863 return mPackageTrackingReceiver; 864 } 865 866 @Nullable getJournal()867 public DataChangedJournal getJournal() { 868 return mJournal; 869 } 870 setJournal(@ullable DataChangedJournal journal)871 public void setJournal(@Nullable DataChangedJournal journal) { 872 mJournal = journal; 873 } 874 getRng()875 public SecureRandom getRng() { 876 return mRng; 877 } 878 setAncestralPackages(Set<String> ancestralPackages)879 public void setAncestralPackages(Set<String> ancestralPackages) { 880 mAncestralPackages = ancestralPackages; 881 } 882 setAncestralToken(long ancestralToken)883 public void setAncestralToken(long ancestralToken) { 884 mAncestralToken = ancestralToken; 885 } 886 setAncestralOperationType(@perationType int operationType)887 public void setAncestralOperationType(@OperationType int operationType) { 888 mAncestralOperationType = operationType; 889 } 890 getCurrentToken()891 public long getCurrentToken() { 892 return mCurrentToken; 893 } 894 setCurrentToken(long currentToken)895 public void setCurrentToken(long currentToken) { 896 mCurrentToken = currentToken; 897 } 898 getPendingInits()899 public ArraySet<String> getPendingInits() { 900 return mPendingInits; 901 } 902 903 /** Clear all pending transport initializations. */ clearPendingInits()904 public void clearPendingInits() { 905 mPendingInits.clear(); 906 } 907 setRunningFullBackupTask( PerformFullTransportBackupTask runningFullBackupTask)908 public void setRunningFullBackupTask( 909 PerformFullTransportBackupTask runningFullBackupTask) { 910 mRunningFullBackupTask = runningFullBackupTask; 911 } 912 913 /** 914 * Utility: build a new random integer token. The low bits are the ordinal of the operation for 915 * near-time uniqueness, and the upper bits are random for app-side unpredictability. 916 */ generateRandomIntegerToken()917 public int generateRandomIntegerToken() { 918 int token = mTokenGenerator.nextInt(); 919 if (token < 0) token = -token; 920 token &= ~0xFF; 921 token |= (mNextToken.incrementAndGet() & 0xFF); 922 return token; 923 } 924 925 /** 926 * Construct a backup agent instance for the metadata pseudopackage. This is a process-local 927 * non-lifecycle agent instance, so we manually set up the context topology for it. 928 */ makeMetadataAgent()929 public BackupAgent makeMetadataAgent() { 930 return makeMetadataAgentWithEligibilityRules(mScheduledBackupEligibility); 931 } 932 makeMetadataAgentWithEligibilityRules( BackupEligibilityRules backupEligibilityRules)933 public BackupAgent makeMetadataAgentWithEligibilityRules( 934 BackupEligibilityRules backupEligibilityRules) { 935 PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager, mUserId, 936 backupEligibilityRules); 937 pmAgent.attach(mContext); 938 pmAgent.onCreate(UserHandle.of(mUserId)); 939 return pmAgent; 940 } 941 942 /** 943 * Same as {@link #makeMetadataAgent()} but with explicit package-set configuration. 944 */ makeMetadataAgent(List<PackageInfo> packages)945 public PackageManagerBackupAgent makeMetadataAgent(List<PackageInfo> packages) { 946 PackageManagerBackupAgent pmAgent = 947 new PackageManagerBackupAgent(mPackageManager, packages, mUserId); 948 pmAgent.attach(mContext); 949 pmAgent.onCreate(UserHandle.of(mUserId)); 950 return pmAgent; 951 } 952 initPackageTracking()953 private void initPackageTracking() { 954 if (MORE_DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, "` tracking")); 955 956 // Remember our ancestral dataset 957 mTokenFile = new File(mBaseStateDir, "ancestral"); 958 try (DataInputStream tokenStream = new DataInputStream(new BufferedInputStream( 959 new FileInputStream(mTokenFile)))) { 960 int version = tokenStream.readInt(); 961 if (version == CURRENT_ANCESTRAL_RECORD_VERSION) { 962 mAncestralToken = tokenStream.readLong(); 963 mCurrentToken = tokenStream.readLong(); 964 965 int numPackages = tokenStream.readInt(); 966 if (numPackages >= 0) { 967 mAncestralPackages = new HashSet<>(); 968 for (int i = 0; i < numPackages; i++) { 969 String pkgName = tokenStream.readUTF(); 970 mAncestralPackages.add(pkgName); 971 } 972 } 973 } 974 } catch (FileNotFoundException fnf) { 975 // Probably innocuous 976 Slog.v(TAG, addUserIdToLogMessage(mUserId, "No ancestral data")); 977 } catch (IOException e) { 978 Slog.w(TAG, addUserIdToLogMessage(mUserId, "Unable to read token file"), e); 979 } 980 981 mProcessedPackagesJournal = new ProcessedPackagesJournal(mBaseStateDir); 982 mProcessedPackagesJournal.init(); 983 984 synchronized (mQueueLock) { 985 // Resume the full-data backup queue 986 mFullBackupQueue = readFullBackupSchedule(); 987 } 988 989 // Register for broadcasts about package changes. 990 IntentFilter filter = new IntentFilter(); 991 filter.addAction(Intent.ACTION_PACKAGE_ADDED); 992 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 993 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 994 filter.addDataScheme("package"); 995 mContext.registerReceiverAsUser( 996 mPackageTrackingReceiver, 997 UserHandle.of(mUserId), 998 filter, 999 /* broadcastPermission */ null, 1000 /* scheduler */ null); 1001 1002 // Register for events related to sdcard installation. 1003 IntentFilter sdFilter = new IntentFilter(); 1004 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 1005 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 1006 mContext.registerReceiverAsUser( 1007 mPackageTrackingReceiver, 1008 UserHandle.of(mUserId), 1009 sdFilter, 1010 /* broadcastPermission */ null, 1011 /* scheduler */ null); 1012 } 1013 readFullBackupSchedule()1014 private ArrayList<FullBackupEntry> readFullBackupSchedule() { 1015 boolean changed = false; 1016 ArrayList<FullBackupEntry> schedule = null; 1017 List<PackageInfo> apps = 1018 PackageManagerBackupAgent.getStorableApplications(mPackageManager, mUserId, 1019 mScheduledBackupEligibility); 1020 1021 if (mFullBackupScheduleFile.exists()) { 1022 try (FileInputStream fstream = new FileInputStream(mFullBackupScheduleFile); 1023 BufferedInputStream bufStream = new BufferedInputStream(fstream); 1024 DataInputStream in = new DataInputStream(bufStream)) { 1025 int version = in.readInt(); 1026 if (version != SCHEDULE_FILE_VERSION) { 1027 Slog.e( 1028 TAG, 1029 addUserIdToLogMessage( 1030 mUserId, "Unknown backup schedule version " + version)); 1031 return null; 1032 } 1033 1034 final int numPackages = in.readInt(); 1035 schedule = new ArrayList<>(numPackages); 1036 1037 // HashSet instead of ArraySet specifically because we want the eventual 1038 // lookups against O(hundreds) of entries to be as fast as possible, and 1039 // we discard the set immediately after the scan so the extra memory 1040 // overhead is transient. 1041 HashSet<String> foundApps = new HashSet<>(numPackages); 1042 1043 for (int i = 0; i < numPackages; i++) { 1044 String pkgName = in.readUTF(); 1045 long lastBackup = in.readLong(); 1046 foundApps.add(pkgName); // all apps that we've addressed already 1047 try { 1048 PackageInfo pkg = mPackageManager.getPackageInfoAsUser(pkgName, 0, mUserId); 1049 if (mScheduledBackupEligibility.appGetsFullBackup(pkg) 1050 && mScheduledBackupEligibility.appIsEligibleForBackup( 1051 pkg.applicationInfo)) { 1052 schedule.add(new FullBackupEntry(pkgName, lastBackup)); 1053 } else { 1054 if (DEBUG) { 1055 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Package " + pkgName 1056 + " no longer eligible for full backup")); 1057 } 1058 } 1059 } catch (NameNotFoundException e) { 1060 if (DEBUG) { 1061 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Package " + pkgName 1062 + " not installed; dropping from full backup")); 1063 } 1064 } 1065 } 1066 1067 // New apps can arrive "out of band" via OTA and similar, so we also need to 1068 // scan to make sure that we're tracking all full-backup candidates properly 1069 for (PackageInfo app : apps) { 1070 if (mScheduledBackupEligibility.appGetsFullBackup(app) 1071 && mScheduledBackupEligibility.appIsEligibleForBackup( 1072 app.applicationInfo)) { 1073 if (!foundApps.contains(app.packageName)) { 1074 if (MORE_DEBUG) { 1075 Slog.i( 1076 TAG, 1077 addUserIdToLogMessage( 1078 mUserId, 1079 "New full backup app " 1080 + app.packageName 1081 + " found")); 1082 } 1083 schedule.add(new FullBackupEntry(app.packageName, 0)); 1084 changed = true; 1085 } 1086 } 1087 } 1088 1089 Collections.sort(schedule); 1090 } catch (Exception e) { 1091 Slog.e(TAG, addUserIdToLogMessage(mUserId, "Unable to read backup schedule"), e); 1092 mFullBackupScheduleFile.delete(); 1093 schedule = null; 1094 } 1095 } 1096 1097 if (schedule == null) { 1098 // no prior queue record, or unable to read it. Set up the queue 1099 // from scratch. 1100 changed = true; 1101 schedule = new ArrayList<>(apps.size()); 1102 for (PackageInfo info : apps) { 1103 if (mScheduledBackupEligibility.appGetsFullBackup(info) 1104 && mScheduledBackupEligibility.appIsEligibleForBackup( 1105 info.applicationInfo)) { 1106 schedule.add(new FullBackupEntry(info.packageName, 0)); 1107 } 1108 } 1109 } 1110 1111 if (changed) { 1112 writeFullBackupScheduleAsync(); 1113 } 1114 return schedule; 1115 } 1116 1117 private Runnable mFullBackupScheduleWriter = new Runnable() { 1118 @Override 1119 public void run() { 1120 synchronized (mQueueLock) { 1121 try { 1122 ByteArrayOutputStream bufStream = new ByteArrayOutputStream(4096); 1123 DataOutputStream bufOut = new DataOutputStream(bufStream); 1124 bufOut.writeInt(SCHEDULE_FILE_VERSION); 1125 1126 // version 1: 1127 // 1128 // [int] # of packages in the queue = N 1129 // N * { 1130 // [utf8] package name 1131 // [long] last backup time for this package 1132 // } 1133 int numPackages = mFullBackupQueue.size(); 1134 bufOut.writeInt(numPackages); 1135 1136 for (int i = 0; i < numPackages; i++) { 1137 FullBackupEntry entry = mFullBackupQueue.get(i); 1138 bufOut.writeUTF(entry.packageName); 1139 bufOut.writeLong(entry.lastBackup); 1140 } 1141 bufOut.flush(); 1142 1143 AtomicFile af = new AtomicFile(mFullBackupScheduleFile); 1144 FileOutputStream out = af.startWrite(); 1145 out.write(bufStream.toByteArray()); 1146 af.finishWrite(out); 1147 } catch (Exception e) { 1148 Slog.e( 1149 TAG, 1150 addUserIdToLogMessage( 1151 mUserId, "Unable to write backup schedule!"), 1152 e); 1153 } 1154 } 1155 } 1156 }; 1157 writeFullBackupScheduleAsync()1158 private void writeFullBackupScheduleAsync() { 1159 mBackupHandler.removeCallbacks(mFullBackupScheduleWriter); 1160 mBackupHandler.post(mFullBackupScheduleWriter); 1161 } 1162 parseLeftoverJournals()1163 private void parseLeftoverJournals() { 1164 ArrayList<DataChangedJournal> journals = DataChangedJournal.listJournals(mJournalDir); 1165 journals.removeAll(Collections.singletonList(mJournal)); 1166 if (!journals.isEmpty()) { 1167 Slog.i(TAG, addUserIdToLogMessage(mUserId, 1168 "Found " + journals.size() + " stale backup journal(s), scheduling.")); 1169 } 1170 Set<String> packageNames = new LinkedHashSet<>(); 1171 for (DataChangedJournal journal : journals) { 1172 try { 1173 journal.forEach(packageName -> { 1174 if (packageNames.add(packageName)) { 1175 dataChangedImpl(packageName); 1176 } 1177 }); 1178 } catch (IOException e) { 1179 Slog.e(TAG, addUserIdToLogMessage(mUserId, "Can't read " + journal), e); 1180 } 1181 } 1182 if (!packageNames.isEmpty()) { 1183 String msg = "Stale backup journals: Scheduled " + packageNames.size() 1184 + " package(s) total"; 1185 if (MORE_DEBUG) { 1186 msg += ": " + packageNames; 1187 } 1188 Slog.i(TAG, addUserIdToLogMessage(mUserId, msg)); 1189 } 1190 } 1191 getExcludedRestoreKeys(String packageName)1192 public Set<String> getExcludedRestoreKeys(String packageName) { 1193 return mBackupPreferences.getExcludedRestoreKeysForPackage(packageName); 1194 } 1195 1196 /** Used for generating random salts or passwords. */ randomBytes(int bits)1197 public byte[] randomBytes(int bits) { 1198 byte[] array = new byte[bits / 8]; 1199 mRng.nextBytes(array); 1200 return array; 1201 } 1202 1203 /** For adb backup/restore. */ setBackupPassword(String currentPw, String newPw)1204 public boolean setBackupPassword(String currentPw, String newPw) { 1205 return mBackupPasswordManager.setBackupPassword(currentPw, newPw); 1206 } 1207 1208 /** For adb backup/restore. */ hasBackupPassword()1209 public boolean hasBackupPassword() { 1210 return mBackupPasswordManager.hasBackupPassword(); 1211 } 1212 1213 /** For adb backup/restore. */ backupPasswordMatches(String currentPw)1214 public boolean backupPasswordMatches(String currentPw) { 1215 return mBackupPasswordManager.backupPasswordMatches(currentPw); 1216 } 1217 1218 /** 1219 * Maintain persistent state around whether need to do an initialize operation. This will lock 1220 * on {@link #getQueueLock()}. 1221 */ recordInitPending( boolean isPending, String transportName, String transportDirName)1222 public void recordInitPending( 1223 boolean isPending, String transportName, String transportDirName) { 1224 synchronized (mQueueLock) { 1225 if (MORE_DEBUG) { 1226 Slog.i( 1227 TAG, 1228 addUserIdToLogMessage( 1229 mUserId, 1230 "recordInitPending(" 1231 + isPending 1232 + ") on transport " 1233 + transportName)); 1234 } 1235 1236 File stateDir = new File(mBaseStateDir, transportDirName); 1237 File initPendingFile = new File(stateDir, INIT_SENTINEL_FILE_NAME); 1238 1239 if (isPending) { 1240 // We need an init before we can proceed with sending backup data. 1241 // Record that with an entry in our set of pending inits, as well as 1242 // journaling it via creation of a sentinel file. 1243 mPendingInits.add(transportName); 1244 try { 1245 (new FileOutputStream(initPendingFile)).close(); 1246 } catch (IOException ioe) { 1247 // Something is badly wrong with our permissions; just try to move on 1248 } 1249 } else { 1250 // No more initialization needed; wipe the journal and reset our state. 1251 initPendingFile.delete(); 1252 mPendingInits.remove(transportName); 1253 } 1254 } 1255 } 1256 1257 /** 1258 * Reset all of our bookkeeping because the backend data has been wiped (for example due to idle 1259 * expiry), so we must re-upload all saved settings. 1260 */ resetBackupState(File stateFileDir)1261 public void resetBackupState(File stateFileDir) { 1262 synchronized (mQueueLock) { 1263 mProcessedPackagesJournal.reset(); 1264 1265 mCurrentToken = 0; 1266 writeRestoreTokens(); 1267 1268 // Remove all the state files 1269 for (File sf : stateFileDir.listFiles()) { 1270 // ... but don't touch the needs-init sentinel 1271 if (!sf.getName().equals(INIT_SENTINEL_FILE_NAME)) { 1272 sf.delete(); 1273 } 1274 } 1275 } 1276 1277 // Enqueue a new backup of every participant 1278 synchronized (mBackupParticipants) { 1279 final int numParticipants = mBackupParticipants.size(); 1280 for (int i = 0; i < numParticipants; i++) { 1281 HashSet<String> participants = mBackupParticipants.valueAt(i); 1282 if (participants != null) { 1283 for (String packageName : participants) { 1284 dataChangedImpl(packageName); 1285 } 1286 } 1287 } 1288 } 1289 } 1290 onTransportRegistered(String transportName, String transportDirName)1291 private void onTransportRegistered(String transportName, String transportDirName) { 1292 if (DEBUG) { 1293 long timeMs = SystemClock.elapsedRealtime() - mRegisterTransportsRequestedTime; 1294 Slog.d( 1295 TAG, 1296 addUserIdToLogMessage( 1297 mUserId, 1298 "Transport " 1299 + transportName 1300 + " registered " 1301 + timeMs 1302 + "ms after first request (delay = " 1303 + INITIALIZATION_DELAY_MILLIS 1304 + "ms)")); 1305 } 1306 1307 File stateDir = new File(mBaseStateDir, transportDirName); 1308 stateDir.mkdirs(); 1309 1310 File initSentinel = new File(stateDir, INIT_SENTINEL_FILE_NAME); 1311 if (initSentinel.exists()) { 1312 synchronized (mQueueLock) { 1313 mPendingInits.add(transportName); 1314 1315 // TODO: pick a better starting time than now + 1 minute 1316 long delay = 1000 * 60; // one minute, in milliseconds 1317 mAlarmManager.set(AlarmManager.RTC_WAKEUP, 1318 System.currentTimeMillis() + delay, mRunInitIntent); 1319 } 1320 } 1321 } 1322 1323 /** 1324 * A {@link BroadcastReceiver} tracking changes to packages and sd cards in order to update our 1325 * internal bookkeeping. 1326 */ 1327 private BroadcastReceiver mPackageTrackingReceiver = new BroadcastReceiver() { 1328 public void onReceive(Context context, Intent intent) { 1329 if (MORE_DEBUG) { 1330 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Received broadcast " + intent)); 1331 } 1332 1333 String action = intent.getAction(); 1334 boolean replacing = false; 1335 boolean added = false; 1336 boolean changed = false; 1337 Bundle extras = intent.getExtras(); 1338 String[] packageList = null; 1339 1340 if (Intent.ACTION_PACKAGE_ADDED.equals(action) 1341 || Intent.ACTION_PACKAGE_REMOVED.equals(action) 1342 || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { 1343 Uri uri = intent.getData(); 1344 if (uri == null) { 1345 return; 1346 } 1347 1348 String packageName = uri.getSchemeSpecificPart(); 1349 if (packageName != null) { 1350 packageList = new String[] {packageName}; 1351 } 1352 1353 changed = Intent.ACTION_PACKAGE_CHANGED.equals(action); 1354 if (changed) { 1355 // Look at new transport states for package changed events. 1356 String[] components = 1357 intent.getStringArrayExtra( 1358 Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); 1359 1360 if (MORE_DEBUG) { 1361 Slog.i( 1362 TAG, 1363 addUserIdToLogMessage( 1364 mUserId, "Package " + packageName + " changed")); 1365 for (int i = 0; i < components.length; i++) { 1366 Slog.i( 1367 TAG, 1368 addUserIdToLogMessage( 1369 mUserId, " * " + components[i])); 1370 } 1371 } 1372 1373 mBackupHandler.post( 1374 () -> 1375 mTransportManager.onPackageChanged( 1376 packageName, components)); 1377 return; 1378 } 1379 1380 added = Intent.ACTION_PACKAGE_ADDED.equals(action); 1381 replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false); 1382 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) { 1383 added = true; 1384 packageList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 1385 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { 1386 added = false; 1387 packageList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 1388 } 1389 1390 if (packageList == null || packageList.length == 0) { 1391 return; 1392 } 1393 1394 int uid = extras.getInt(Intent.EXTRA_UID); 1395 if (added) { 1396 synchronized (mBackupParticipants) { 1397 if (replacing) { 1398 // Remove the entry under the old uid and fall through to re-add. If 1399 // an app 1400 // just opted into key/value backup, add it as a known participant. 1401 removePackageParticipantsLocked(packageList, uid); 1402 } 1403 addPackageParticipantsLocked(packageList); 1404 } 1405 1406 long now = System.currentTimeMillis(); 1407 for (String packageName : packageList) { 1408 try { 1409 PackageInfo app = 1410 mPackageManager.getPackageInfoAsUser( 1411 packageName, /* flags */ 0, mUserId); 1412 if (mScheduledBackupEligibility.appGetsFullBackup(app) 1413 && mScheduledBackupEligibility.appIsEligibleForBackup( 1414 app.applicationInfo)) { 1415 enqueueFullBackup(packageName, now); 1416 scheduleNextFullBackupJob(0); 1417 } else { 1418 // The app might have just transitioned out of full-data into 1419 // doing 1420 // key/value backups, or might have just disabled backups 1421 // entirely. Make 1422 // sure it is no longer in the full-data queue. 1423 synchronized (mQueueLock) { 1424 dequeueFullBackupLocked(packageName); 1425 } 1426 writeFullBackupScheduleAsync(); 1427 } 1428 1429 mBackupHandler.post( 1430 () -> mTransportManager.onPackageAdded(packageName)); 1431 } catch (NameNotFoundException e) { 1432 if (DEBUG) { 1433 Slog.w( 1434 TAG, 1435 addUserIdToLogMessage( 1436 mUserId, 1437 "Can't resolve new app " + packageName)); 1438 } 1439 } 1440 } 1441 1442 // Whenever a package is added or updated we need to update the package 1443 // metadata 1444 // bookkeeping. 1445 dataChangedImpl(PACKAGE_MANAGER_SENTINEL); 1446 } else { 1447 if (!replacing) { 1448 // Outright removal. In the full-data case, the app will be dropped from 1449 // the 1450 // queue when its (now obsolete) name comes up again for backup. 1451 synchronized (mBackupParticipants) { 1452 removePackageParticipantsLocked(packageList, uid); 1453 } 1454 } 1455 1456 for (String packageName : packageList) { 1457 mBackupHandler.post( 1458 () -> mTransportManager.onPackageRemoved(packageName)); 1459 } 1460 } 1461 } 1462 }; 1463 1464 // Add the backup agents in the given packages to our set of known backup participants. 1465 // If 'packageNames' is null, adds all backup agents in the whole system. addPackageParticipantsLocked(String[] packageNames)1466 private void addPackageParticipantsLocked(String[] packageNames) { 1467 // Look for apps that define the android:backupAgent attribute 1468 List<PackageInfo> targetApps = allAgentPackages(); 1469 if (packageNames != null) { 1470 if (MORE_DEBUG) { 1471 Slog.v( 1472 TAG, 1473 addUserIdToLogMessage( 1474 mUserId, "addPackageParticipantsLocked: #" + packageNames.length)); 1475 } 1476 for (String packageName : packageNames) { 1477 addPackageParticipantsLockedInner(packageName, targetApps); 1478 } 1479 } else { 1480 if (MORE_DEBUG) { 1481 Slog.v(TAG, addUserIdToLogMessage(mUserId, "addPackageParticipantsLocked: all")); 1482 } 1483 addPackageParticipantsLockedInner(null, targetApps); 1484 } 1485 } 1486 addPackageParticipantsLockedInner(String packageName, List<PackageInfo> targetPkgs)1487 private void addPackageParticipantsLockedInner(String packageName, 1488 List<PackageInfo> targetPkgs) { 1489 if (MORE_DEBUG) { 1490 Slog.v( 1491 TAG, 1492 addUserIdToLogMessage( 1493 mUserId, "Examining " + packageName + " for backup agent")); 1494 } 1495 1496 for (PackageInfo pkg : targetPkgs) { 1497 if (packageName == null || pkg.packageName.equals(packageName)) { 1498 int uid = pkg.applicationInfo.uid; 1499 HashSet<String> set = mBackupParticipants.get(uid); 1500 if (set == null) { 1501 set = new HashSet<>(); 1502 mBackupParticipants.put(uid, set); 1503 } 1504 set.add(pkg.packageName); 1505 if (MORE_DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, "Agent found; added")); 1506 1507 // Schedule a backup for it on general principles 1508 if (MORE_DEBUG) { 1509 Slog.i( 1510 TAG, 1511 addUserIdToLogMessage( 1512 mUserId, "Scheduling backup for new app " + pkg.packageName)); 1513 } 1514 Message msg = mBackupHandler 1515 .obtainMessage(MSG_SCHEDULE_BACKUP_PACKAGE, pkg.packageName); 1516 mBackupHandler.sendMessage(msg); 1517 } 1518 } 1519 } 1520 1521 // Remove the given packages' entries from our known active set. removePackageParticipantsLocked(String[] packageNames, int oldUid)1522 private void removePackageParticipantsLocked(String[] packageNames, int oldUid) { 1523 if (packageNames == null) { 1524 Slog.w(TAG, addUserIdToLogMessage(mUserId, "removePackageParticipants with null list")); 1525 return; 1526 } 1527 1528 if (MORE_DEBUG) { 1529 Slog.v( 1530 TAG, 1531 addUserIdToLogMessage( 1532 mUserId, 1533 "removePackageParticipantsLocked: uid=" 1534 + oldUid 1535 + " #" 1536 + packageNames.length)); 1537 } 1538 for (String pkg : packageNames) { 1539 // Known previous UID, so we know which package set to check 1540 HashSet<String> set = mBackupParticipants.get(oldUid); 1541 if (set != null && set.contains(pkg)) { 1542 removePackageFromSetLocked(set, pkg); 1543 if (set.isEmpty()) { 1544 if (MORE_DEBUG) { 1545 Slog.v( 1546 TAG, 1547 addUserIdToLogMessage( 1548 mUserId, " last one of this uid; purging set")); 1549 } 1550 mBackupParticipants.remove(oldUid); 1551 } 1552 } 1553 } 1554 } 1555 removePackageFromSetLocked(final HashSet<String> set, final String packageName)1556 private void removePackageFromSetLocked(final HashSet<String> set, 1557 final String packageName) { 1558 if (set.contains(packageName)) { 1559 // Found it. Remove this one package from the bookkeeping, and 1560 // if it's the last participating app under this uid we drop the 1561 // (now-empty) set as well. 1562 // Note that we deliberately leave it 'known' in the "ever backed up" 1563 // bookkeeping so that its current-dataset data will be retrieved 1564 // if the app is subsequently reinstalled 1565 if (MORE_DEBUG) { 1566 Slog.v( 1567 TAG, 1568 addUserIdToLogMessage(mUserId, " removing participant " + packageName)); 1569 } 1570 set.remove(packageName); 1571 mPendingBackups.remove(packageName); 1572 } 1573 } 1574 1575 // Returns the set of all applications that define an android:backupAgent attribute allAgentPackages()1576 private List<PackageInfo> allAgentPackages() { 1577 // !!! TODO: cache this and regenerate only when necessary 1578 int flags = PackageManager.GET_SIGNING_CERTIFICATES; 1579 List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(flags, mUserId); 1580 int numPackages = packages.size(); 1581 for (int a = numPackages - 1; a >= 0; a--) { 1582 PackageInfo pkg = packages.get(a); 1583 try { 1584 ApplicationInfo app = pkg.applicationInfo; 1585 if (((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) 1586 || app.backupAgentName == null 1587 || (app.flags & ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0) { 1588 packages.remove(a); 1589 } else { 1590 // we will need the shared library path, so look that up and store it here. 1591 // This is used implicitly when we pass the PackageInfo object off to 1592 // the Activity Manager to launch the app for backup/restore purposes. 1593 app = mPackageManager.getApplicationInfoAsUser(pkg.packageName, 1594 PackageManager.GET_SHARED_LIBRARY_FILES, mUserId); 1595 pkg.applicationInfo.sharedLibraryFiles = app.sharedLibraryFiles; 1596 pkg.applicationInfo.sharedLibraryInfos = app.sharedLibraryInfos; 1597 } 1598 } catch (NameNotFoundException e) { 1599 packages.remove(a); 1600 } 1601 } 1602 return packages; 1603 } 1604 1605 /** 1606 * Called from the backup tasks: record that the given app has been successfully backed up at 1607 * least once. This includes both key/value and full-data backups through the transport. 1608 */ logBackupComplete(String packageName)1609 public void logBackupComplete(String packageName) { 1610 if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) return; 1611 1612 for (String receiver : mConstants.getBackupFinishedNotificationReceivers()) { 1613 final Intent notification = new Intent(); 1614 notification.setAction(BACKUP_FINISHED_ACTION); 1615 notification.setPackage(receiver); 1616 notification.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES 1617 | Intent.FLAG_RECEIVER_FOREGROUND); 1618 notification.putExtra(BACKUP_FINISHED_PACKAGE_EXTRA, packageName); 1619 mContext.sendBroadcastAsUser(notification, UserHandle.of(mUserId)); 1620 } 1621 1622 mProcessedPackagesJournal.addPackage(packageName); 1623 } 1624 1625 /** 1626 * Persistently record the current and ancestral backup tokens, as well as the set of packages 1627 * with data available in the ancestral dataset. 1628 */ writeRestoreTokens()1629 public void writeRestoreTokens() { 1630 try (RandomAccessFile af = new RandomAccessFile(mTokenFile, "rwd")) { 1631 // First, the version number of this record, for futureproofing 1632 af.writeInt(CURRENT_ANCESTRAL_RECORD_VERSION); 1633 1634 // Write the ancestral and current tokens 1635 af.writeLong(mAncestralToken); 1636 af.writeLong(mCurrentToken); 1637 1638 // Now write the set of ancestral packages 1639 if (mAncestralPackages == null) { 1640 af.writeInt(-1); 1641 } else { 1642 af.writeInt(mAncestralPackages.size()); 1643 if (DEBUG) { 1644 Slog.v( 1645 TAG, 1646 addUserIdToLogMessage( 1647 mUserId, "Ancestral packages: " + mAncestralPackages.size())); 1648 } 1649 for (String pkgName : mAncestralPackages) { 1650 af.writeUTF(pkgName); 1651 if (MORE_DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, " " + pkgName)); 1652 } 1653 } 1654 } catch (IOException e) { 1655 Slog.w(TAG, addUserIdToLogMessage(mUserId, "Unable to write token file:"), e); 1656 } 1657 } 1658 1659 /** Fires off a backup agent, blocking until it attaches or times out. */ 1660 @Nullable bindToAgentSynchronous(ApplicationInfo app, int mode, @OperationType int operationType)1661 public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode, 1662 @OperationType int operationType) { 1663 IBackupAgent agent = null; 1664 synchronized (mAgentConnectLock) { 1665 mConnecting = true; 1666 mConnectedAgent = null; 1667 try { 1668 if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId, 1669 operationType)) { 1670 Slog.d(TAG, addUserIdToLogMessage(mUserId, "awaiting agent for " + app)); 1671 1672 // success; wait for the agent to arrive 1673 // only wait 10 seconds for the bind to happen 1674 long timeoutMark = System.currentTimeMillis() + BIND_TIMEOUT_INTERVAL; 1675 while (mConnecting && mConnectedAgent == null 1676 && (System.currentTimeMillis() < timeoutMark)) { 1677 try { 1678 mAgentConnectLock.wait(5000); 1679 } catch (InterruptedException e) { 1680 // just bail 1681 Slog.w(TAG, addUserIdToLogMessage(mUserId, "Interrupted: " + e)); 1682 mConnecting = false; 1683 mConnectedAgent = null; 1684 } 1685 } 1686 1687 // if we timed out with no connect, abort and move on 1688 if (mConnecting) { 1689 Slog.w( 1690 TAG, 1691 addUserIdToLogMessage(mUserId, "Timeout waiting for agent " + app)); 1692 mConnectedAgent = null; 1693 } 1694 if (DEBUG) { 1695 Slog.i(TAG, addUserIdToLogMessage(mUserId, "got agent " + mConnectedAgent)); 1696 } 1697 agent = mConnectedAgent; 1698 } 1699 } catch (RemoteException e) { 1700 // can't happen - ActivityManager is local 1701 } 1702 } 1703 if (agent == null) { 1704 mActivityManagerInternal.clearPendingBackup(mUserId); 1705 } 1706 return agent; 1707 } 1708 1709 /** Unbind from a backup agent. */ unbindAgent(ApplicationInfo app)1710 public void unbindAgent(ApplicationInfo app) { 1711 try { 1712 mActivityManager.unbindBackupAgent(app); 1713 } catch (RemoteException e) { 1714 // Can't happen - activity manager is local 1715 } 1716 } 1717 1718 /** 1719 * Clear an application's data after a failed restore, blocking until the operation completes or 1720 * times out. 1721 */ clearApplicationDataAfterRestoreFailure(String packageName)1722 public void clearApplicationDataAfterRestoreFailure(String packageName) { 1723 clearApplicationDataSynchronous(packageName, true, false); 1724 } 1725 1726 /** 1727 * Clear an application's data before restore, blocking until the operation completes or times 1728 * out. 1729 */ clearApplicationDataBeforeRestore(String packageName)1730 public void clearApplicationDataBeforeRestore(String packageName) { 1731 clearApplicationDataSynchronous(packageName, false, true); 1732 } 1733 1734 /** 1735 * Clear an application's data, blocking until the operation completes or times out. 1736 * 1737 * @param checkFlagAllowClearUserDataOnFailedRestore if {@code true} uses 1738 * {@link ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE} to decide if 1739 * clearing data is allowed after a failed restore. 1740 * 1741 * @param keepSystemState if {@code true}, we don't clear system state such as already restored 1742 * notification settings, permission grants, etc. 1743 */ clearApplicationDataSynchronous(String packageName, boolean checkFlagAllowClearUserDataOnFailedRestore, boolean keepSystemState)1744 private void clearApplicationDataSynchronous(String packageName, 1745 boolean checkFlagAllowClearUserDataOnFailedRestore, boolean keepSystemState) { 1746 try { 1747 ApplicationInfo applicationInfo = mPackageManager.getPackageInfoAsUser( 1748 packageName, 0, mUserId).applicationInfo; 1749 1750 boolean shouldClearData; 1751 if (checkFlagAllowClearUserDataOnFailedRestore 1752 && applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) { 1753 shouldClearData = (applicationInfo.privateFlags 1754 & ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE) != 0; 1755 } else { 1756 shouldClearData = 1757 (applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) != 0; 1758 } 1759 1760 if (!shouldClearData) { 1761 if (MORE_DEBUG) { 1762 Slog.i( 1763 TAG, 1764 addUserIdToLogMessage( 1765 mUserId, 1766 "Clearing app data is not allowed so not wiping " 1767 + packageName)); 1768 } 1769 return; 1770 } 1771 } catch (NameNotFoundException e) { 1772 Slog.w( 1773 TAG, 1774 addUserIdToLogMessage( 1775 mUserId, "Tried to clear data for " + packageName + " but not found")); 1776 return; 1777 } 1778 1779 ClearDataObserver observer = new ClearDataObserver(this); 1780 1781 synchronized (mClearDataLock) { 1782 mClearingData = true; 1783 try { 1784 mActivityManager.clearApplicationUserData(packageName, keepSystemState, observer, 1785 mUserId); 1786 } catch (RemoteException e) { 1787 // can't happen because the activity manager is in this process 1788 } 1789 1790 // Only wait 30 seconds for the clear data to happen. 1791 long timeoutMark = System.currentTimeMillis() + CLEAR_DATA_TIMEOUT_INTERVAL; 1792 while (mClearingData && (System.currentTimeMillis() < timeoutMark)) { 1793 try { 1794 mClearDataLock.wait(5000); 1795 } catch (InterruptedException e) { 1796 // won't happen, but still. 1797 mClearingData = false; 1798 Slog.w( 1799 TAG, 1800 addUserIdToLogMessage( 1801 mUserId, 1802 "Interrupted while waiting for " 1803 + packageName 1804 + " data to be cleared"), 1805 e); 1806 } 1807 } 1808 1809 if (mClearingData) { 1810 Slog.w( 1811 TAG, 1812 addUserIdToLogMessage( 1813 mUserId, "Clearing app data for " + packageName + " timed out")); 1814 } 1815 } 1816 } 1817 getEligibilityRulesForRestoreAtInstall(long restoreToken)1818 private BackupEligibilityRules getEligibilityRulesForRestoreAtInstall(long restoreToken) { 1819 if (mAncestralOperationType == OperationType.MIGRATION && restoreToken == mAncestralToken) { 1820 return getEligibilityRulesForOperation(OperationType.MIGRATION); 1821 } else { 1822 // If we're not using the ancestral data set, it means we're restoring from a backup 1823 // that happened on this device. 1824 return mScheduledBackupEligibility; 1825 } 1826 } 1827 1828 /** 1829 * Get the restore-set token for the best-available restore set for this {@code packageName}: 1830 * the active set if possible, else the ancestral one. Returns zero if none available. 1831 */ getAvailableRestoreToken(String packageName)1832 public long getAvailableRestoreToken(String packageName) { 1833 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 1834 "getAvailableRestoreToken"); 1835 1836 long token = mAncestralToken; 1837 synchronized (mQueueLock) { 1838 if (mCurrentToken != 0 && mProcessedPackagesJournal.hasBeenProcessed(packageName)) { 1839 if (MORE_DEBUG) { 1840 Slog.i( 1841 TAG, 1842 addUserIdToLogMessage( 1843 mUserId, "App in ever-stored, so using current token")); 1844 } 1845 token = mCurrentToken; 1846 } 1847 } 1848 if (MORE_DEBUG) { 1849 Slog.i(TAG, addUserIdToLogMessage(mUserId, "getAvailableRestoreToken() == " + token)); 1850 } 1851 return token; 1852 } 1853 1854 /** 1855 * Requests a backup for the inputted {@code packages}. 1856 * 1857 * @see #requestBackup(String[], IBackupObserver, IBackupManagerMonitor, int). 1858 */ requestBackup(String[] packages, IBackupObserver observer, int flags)1859 public int requestBackup(String[] packages, IBackupObserver observer, int flags) { 1860 return requestBackup(packages, observer, null, flags); 1861 } 1862 1863 /** 1864 * Requests a backup for the inputted {@code packages} with a specified {@link 1865 * IBackupManagerMonitor} and {@link OperationType}. 1866 */ requestBackup(String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, int flags)1867 public int requestBackup(String[] packages, IBackupObserver observer, 1868 IBackupManagerMonitor monitor, int flags) { 1869 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup"); 1870 1871 if (packages == null || packages.length < 1) { 1872 Slog.e(TAG, addUserIdToLogMessage(mUserId, "No packages named for backup request")); 1873 BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED); 1874 monitor = BackupManagerMonitorUtils.monitorEvent(monitor, 1875 BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES, 1876 null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null); 1877 throw new IllegalArgumentException("No packages are provided for backup"); 1878 } 1879 1880 if (!mEnabled || !mSetupComplete) { 1881 Slog.i( 1882 TAG, 1883 addUserIdToLogMessage(mUserId, "Backup requested but enabled=" 1884 + mEnabled 1885 + " setupComplete=" 1886 + mSetupComplete)); 1887 BackupObserverUtils.sendBackupFinished(observer, 1888 BackupManager.ERROR_BACKUP_NOT_ALLOWED); 1889 final int logTag = mSetupComplete 1890 ? BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED 1891 : BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED; 1892 monitor = BackupManagerMonitorUtils.monitorEvent(monitor, logTag, null, 1893 BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null); 1894 return BackupManager.ERROR_BACKUP_NOT_ALLOWED; 1895 } 1896 1897 final TransportClient transportClient; 1898 final String transportDirName; 1899 int operationType; 1900 try { 1901 transportDirName = 1902 mTransportManager.getTransportDirName( 1903 mTransportManager.getCurrentTransportName()); 1904 transportClient = 1905 mTransportManager.getCurrentTransportClientOrThrow("BMS.requestBackup()"); 1906 operationType = getOperationTypeFromTransport(transportClient); 1907 } catch (TransportNotRegisteredException | TransportNotAvailableException 1908 | RemoteException e) { 1909 BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED); 1910 monitor = BackupManagerMonitorUtils.monitorEvent(monitor, 1911 BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL, 1912 null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null); 1913 return BackupManager.ERROR_TRANSPORT_ABORTED; 1914 } 1915 1916 OnTaskFinishedListener listener = 1917 caller -> mTransportManager.disposeOfTransportClient(transportClient, caller); 1918 BackupEligibilityRules backupEligibilityRules = getEligibilityRulesForOperation( 1919 operationType); 1920 1921 Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP); 1922 msg.obj = getRequestBackupParams(packages, observer, monitor, flags, backupEligibilityRules, 1923 transportClient, transportDirName, listener); 1924 mBackupHandler.sendMessage(msg); 1925 return BackupManager.SUCCESS; 1926 } 1927 1928 @VisibleForTesting getRequestBackupParams(String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, int flags, BackupEligibilityRules backupEligibilityRules, TransportClient transportClient, String transportDirName, OnTaskFinishedListener listener)1929 BackupParams getRequestBackupParams(String[] packages, IBackupObserver observer, 1930 IBackupManagerMonitor monitor, int flags, BackupEligibilityRules backupEligibilityRules, 1931 TransportClient transportClient, String transportDirName, 1932 OnTaskFinishedListener listener) { 1933 ArrayList<String> fullBackupList = new ArrayList<>(); 1934 ArrayList<String> kvBackupList = new ArrayList<>(); 1935 for (String packageName : packages) { 1936 if (PACKAGE_MANAGER_SENTINEL.equals(packageName)) { 1937 kvBackupList.add(packageName); 1938 continue; 1939 } 1940 try { 1941 PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageName, 1942 PackageManager.GET_SIGNING_CERTIFICATES, mUserId); 1943 if (!backupEligibilityRules.appIsEligibleForBackup(packageInfo.applicationInfo)) { 1944 BackupObserverUtils.sendBackupOnPackageResult(observer, packageName, 1945 BackupManager.ERROR_BACKUP_NOT_ALLOWED); 1946 continue; 1947 } 1948 if (backupEligibilityRules.appGetsFullBackup(packageInfo)) { 1949 fullBackupList.add(packageInfo.packageName); 1950 } else { 1951 kvBackupList.add(packageInfo.packageName); 1952 } 1953 } catch (NameNotFoundException e) { 1954 BackupObserverUtils.sendBackupOnPackageResult(observer, packageName, 1955 BackupManager.ERROR_PACKAGE_NOT_FOUND); 1956 } 1957 } 1958 1959 EventLog.writeEvent(EventLogTags.BACKUP_REQUESTED, packages.length, kvBackupList.size(), 1960 fullBackupList.size()); 1961 if (MORE_DEBUG) { 1962 Slog.i( 1963 TAG, 1964 addUserIdToLogMessage( 1965 mUserId, 1966 "Backup requested for " 1967 + packages.length 1968 + " packages, of them: " 1969 + fullBackupList.size() 1970 + " full backups, " 1971 + kvBackupList.size() 1972 + " k/v backups")); 1973 } 1974 1975 boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0; 1976 1977 return new BackupParams(transportClient, transportDirName, kvBackupList, fullBackupList, 1978 observer, monitor, listener, /* userInitiated */ true, nonIncrementalBackup, 1979 backupEligibilityRules); 1980 } 1981 1982 /** Cancel all running backups. */ cancelBackups()1983 public void cancelBackups() { 1984 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "cancelBackups"); 1985 if (MORE_DEBUG) { 1986 Slog.i(TAG, addUserIdToLogMessage(mUserId, "cancelBackups() called.")); 1987 } 1988 final long oldToken = Binder.clearCallingIdentity(); 1989 try { 1990 List<Integer> operationsToCancel = new ArrayList<>(); 1991 synchronized (mCurrentOpLock) { 1992 for (int i = 0; i < mCurrentOperations.size(); i++) { 1993 Operation op = mCurrentOperations.valueAt(i); 1994 int token = mCurrentOperations.keyAt(i); 1995 if (op.type == OP_TYPE_BACKUP) { 1996 operationsToCancel.add(token); 1997 } 1998 } 1999 } 2000 for (Integer token : operationsToCancel) { 2001 handleCancel(token, true /* cancelAll */); 2002 } 2003 // We don't want the backup jobs to kick in any time soon. 2004 // Reschedules them to run in the distant future. 2005 KeyValueBackupJob.schedule(mUserId, mContext, BUSY_BACKOFF_MIN_MILLIS, mConstants); 2006 FullBackupJob.schedule(mUserId, mContext, 2 * BUSY_BACKOFF_MIN_MILLIS, mConstants); 2007 } finally { 2008 Binder.restoreCallingIdentity(oldToken); 2009 } 2010 } 2011 2012 /** Schedule a timeout message for the operation identified by {@code token}. */ prepareOperationTimeout(int token, long interval, BackupRestoreTask callback, int operationType)2013 public void prepareOperationTimeout(int token, long interval, BackupRestoreTask callback, 2014 int operationType) { 2015 if (operationType != OP_TYPE_BACKUP_WAIT && operationType != OP_TYPE_RESTORE_WAIT) { 2016 Slog.wtf( 2017 TAG, 2018 addUserIdToLogMessage( 2019 mUserId, 2020 "prepareOperationTimeout() doesn't support operation " 2021 + Integer.toHexString(token) 2022 + " of type " 2023 + operationType)); 2024 return; 2025 } 2026 if (MORE_DEBUG) { 2027 Slog.v( 2028 TAG, 2029 addUserIdToLogMessage( 2030 mUserId, 2031 "starting timeout: token=" 2032 + Integer.toHexString(token) 2033 + " interval=" 2034 + interval 2035 + " callback=" 2036 + callback)); 2037 } 2038 2039 synchronized (mCurrentOpLock) { 2040 mCurrentOperations.put(token, new Operation(OP_PENDING, callback, operationType)); 2041 Message msg = mBackupHandler.obtainMessage(getMessageIdForOperationType(operationType), 2042 token, 0, callback); 2043 mBackupHandler.sendMessageDelayed(msg, interval); 2044 } 2045 } 2046 getMessageIdForOperationType(int operationType)2047 private int getMessageIdForOperationType(int operationType) { 2048 switch (operationType) { 2049 case OP_TYPE_BACKUP_WAIT: 2050 return MSG_BACKUP_OPERATION_TIMEOUT; 2051 case OP_TYPE_RESTORE_WAIT: 2052 return MSG_RESTORE_OPERATION_TIMEOUT; 2053 default: 2054 Slog.wtf( 2055 TAG, 2056 addUserIdToLogMessage( 2057 mUserId, 2058 "getMessageIdForOperationType called on invalid operation type: " 2059 + operationType)); 2060 return -1; 2061 } 2062 } 2063 2064 /** 2065 * Add an operation to the list of currently running operations. Used for cancellation, 2066 * completion and timeout callbacks that act on the operation via the {@code token}. 2067 */ putOperation(int token, Operation operation)2068 public void putOperation(int token, Operation operation) { 2069 if (MORE_DEBUG) { 2070 Slog.d( 2071 TAG, 2072 addUserIdToLogMessage( 2073 mUserId, 2074 "Adding operation token=" 2075 + Integer.toHexString(token) 2076 + ", operation type=" 2077 + operation.type)); 2078 } 2079 synchronized (mCurrentOpLock) { 2080 mCurrentOperations.put(token, operation); 2081 } 2082 } 2083 2084 /** 2085 * Remove an operation from the list of currently running operations. An operation is removed 2086 * when it is completed, cancelled, or timed out, and thus no longer running. 2087 */ removeOperation(int token)2088 public void removeOperation(int token) { 2089 if (MORE_DEBUG) { 2090 Slog.d( 2091 TAG, 2092 addUserIdToLogMessage( 2093 mUserId, "Removing operation token=" + Integer.toHexString(token))); 2094 } 2095 synchronized (mCurrentOpLock) { 2096 if (mCurrentOperations.get(token) == null) { 2097 Slog.w(TAG, addUserIdToLogMessage(mUserId, "Duplicate remove for operation. token=" 2098 + Integer.toHexString(token))); 2099 } 2100 mCurrentOperations.remove(token); 2101 } 2102 } 2103 2104 /** Block until we received an operation complete message (from the agent or cancellation). */ waitUntilOperationComplete(int token)2105 public boolean waitUntilOperationComplete(int token) { 2106 if (MORE_DEBUG) { 2107 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Blocking until operation complete for " 2108 + Integer.toHexString(token))); 2109 } 2110 int finalState = OP_PENDING; 2111 Operation op = null; 2112 synchronized (mCurrentOpLock) { 2113 while (true) { 2114 op = mCurrentOperations.get(token); 2115 if (op == null) { 2116 // mysterious disappearance: treat as success with no callback 2117 break; 2118 } else { 2119 if (op.state == OP_PENDING) { 2120 try { 2121 mCurrentOpLock.wait(); 2122 } catch (InterruptedException e) { 2123 } 2124 // When the wait is notified we loop around and recheck the current state 2125 } else { 2126 if (MORE_DEBUG) { 2127 Slog.d( 2128 TAG, 2129 addUserIdToLogMessage( 2130 mUserId, 2131 "Unblocked waiting for operation token=" 2132 + Integer.toHexString(token))); 2133 } 2134 // No longer pending; we're done 2135 finalState = op.state; 2136 break; 2137 } 2138 } 2139 } 2140 } 2141 2142 removeOperation(token); 2143 if (op != null) { 2144 mBackupHandler.removeMessages(getMessageIdForOperationType(op.type)); 2145 } 2146 if (MORE_DEBUG) { 2147 Slog.v(TAG, addUserIdToLogMessage(mUserId, "operation " + Integer.toHexString(token) 2148 + " complete: finalState=" + finalState)); 2149 } 2150 return finalState == OP_ACKNOWLEDGED; 2151 } 2152 2153 /** Cancel the operation associated with {@code token}. */ handleCancel(int token, boolean cancelAll)2154 public void handleCancel(int token, boolean cancelAll) { 2155 // Notify any synchronous waiters 2156 Operation op = null; 2157 synchronized (mCurrentOpLock) { 2158 op = mCurrentOperations.get(token); 2159 if (MORE_DEBUG) { 2160 if (op == null) { 2161 Slog.w( 2162 TAG, 2163 addUserIdToLogMessage( 2164 mUserId, 2165 "Cancel of token " 2166 + Integer.toHexString(token) 2167 + " but no op found")); 2168 } 2169 } 2170 int state = (op != null) ? op.state : OP_TIMEOUT; 2171 if (state == OP_ACKNOWLEDGED) { 2172 // The operation finished cleanly, so we have nothing more to do. 2173 if (DEBUG) { 2174 Slog.w(TAG, addUserIdToLogMessage(mUserId, "Operation already got an ack." 2175 + "Should have been removed from mCurrentOperations.")); 2176 } 2177 op = null; 2178 mCurrentOperations.delete(token); 2179 } else if (state == OP_PENDING) { 2180 if (DEBUG) { 2181 Slog.v( 2182 TAG, 2183 addUserIdToLogMessage( 2184 mUserId, "Cancel: token=" + Integer.toHexString(token))); 2185 } 2186 op.state = OP_TIMEOUT; 2187 // Can't delete op from mCurrentOperations here. waitUntilOperationComplete may be 2188 // called after we receive cancel here. We need this op's state there. 2189 2190 // Remove all pending timeout messages of types OP_TYPE_BACKUP_WAIT and 2191 // OP_TYPE_RESTORE_WAIT. On the other hand, OP_TYPE_BACKUP cannot time out and 2192 // doesn't require cancellation. 2193 if (op.type == OP_TYPE_BACKUP_WAIT || op.type == OP_TYPE_RESTORE_WAIT) { 2194 mBackupHandler.removeMessages(getMessageIdForOperationType(op.type)); 2195 } 2196 } 2197 mCurrentOpLock.notifyAll(); 2198 } 2199 2200 // If there's a TimeoutHandler for this event, call it 2201 if (op != null && op.callback != null) { 2202 if (MORE_DEBUG) { 2203 Slog.v(TAG, addUserIdToLogMessage(mUserId, " Invoking cancel on " + op.callback)); 2204 } 2205 op.callback.handleCancel(cancelAll); 2206 } 2207 } 2208 2209 /** Returns {@code true} if a backup is currently running, else returns {@code false}. */ isBackupOperationInProgress()2210 public boolean isBackupOperationInProgress() { 2211 synchronized (mCurrentOpLock) { 2212 for (int i = 0; i < mCurrentOperations.size(); i++) { 2213 Operation op = mCurrentOperations.valueAt(i); 2214 if (op.type == OP_TYPE_BACKUP && op.state == OP_PENDING) { 2215 return true; 2216 } 2217 } 2218 } 2219 return false; 2220 } 2221 2222 /** Unbind the backup agent and kill the app if it's a non-system app. */ tearDownAgentAndKill(ApplicationInfo app)2223 public void tearDownAgentAndKill(ApplicationInfo app) { 2224 if (app == null) { 2225 // Null means the system package, so just quietly move on. :) 2226 return; 2227 } 2228 2229 try { 2230 // unbind and tidy up even on timeout or failure, just in case 2231 mActivityManager.unbindBackupAgent(app); 2232 2233 // The agent was running with a stub Application object, so shut it down. 2234 // !!! We hardcode the confirmation UI's package name here rather than use a 2235 // manifest flag! TODO something less direct. 2236 if (!UserHandle.isCore(app.uid) 2237 && !app.packageName.equals("com.android.backupconfirm")) { 2238 if (MORE_DEBUG) { 2239 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Killing agent host process")); 2240 } 2241 mActivityManager.killApplicationProcess(app.processName, app.uid); 2242 } else { 2243 if (MORE_DEBUG) { 2244 Slog.d( 2245 TAG, 2246 addUserIdToLogMessage( 2247 mUserId, "Not killing after operation: " + app.processName)); 2248 } 2249 } 2250 } catch (RemoteException e) { 2251 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Lost app trying to shut down")); 2252 } 2253 } 2254 2255 /** For adb backup/restore. */ deviceIsEncrypted()2256 public boolean deviceIsEncrypted() { 2257 try { 2258 return mStorageManager.getEncryptionState() 2259 != StorageManager.ENCRYPTION_STATE_NONE 2260 && mStorageManager.getPasswordType() 2261 != StorageManager.CRYPT_TYPE_DEFAULT; 2262 } catch (Exception e) { 2263 // If we can't talk to the storagemanager service we have a serious problem; fail 2264 // "secure" i.e. assuming that the device is encrypted. 2265 Slog.e( 2266 TAG, 2267 addUserIdToLogMessage( 2268 mUserId, 2269 "Unable to communicate with storagemanager service: " 2270 + e.getMessage())); 2271 return true; 2272 } 2273 } 2274 2275 // ----- Full-data backup scheduling ----- 2276 2277 /** 2278 * Schedule a job to tell us when it's a good time to run a full backup 2279 */ scheduleNextFullBackupJob(long transportMinLatency)2280 public void scheduleNextFullBackupJob(long transportMinLatency) { 2281 synchronized (mQueueLock) { 2282 if (mFullBackupQueue.size() > 0) { 2283 // schedule the next job at the point in the future when the least-recently 2284 // backed up app comes due for backup again; or immediately if it's already 2285 // due. 2286 final long upcomingLastBackup = mFullBackupQueue.get(0).lastBackup; 2287 final long timeSinceLast = System.currentTimeMillis() - upcomingLastBackup; 2288 final long interval = mConstants.getFullBackupIntervalMilliseconds(); 2289 final long appLatency = (timeSinceLast < interval) ? (interval - timeSinceLast) : 0; 2290 final long latency = Math.max(transportMinLatency, appLatency); 2291 FullBackupJob.schedule(mUserId, mContext, latency, mConstants); 2292 } else { 2293 if (DEBUG_SCHEDULING) { 2294 Slog.i( 2295 TAG, 2296 addUserIdToLogMessage( 2297 mUserId, "Full backup queue empty; not scheduling")); 2298 } 2299 } 2300 } 2301 } 2302 2303 /** 2304 * Remove a package from the full-data queue. 2305 */ 2306 @GuardedBy("mQueueLock") dequeueFullBackupLocked(String packageName)2307 private void dequeueFullBackupLocked(String packageName) { 2308 final int numPackages = mFullBackupQueue.size(); 2309 for (int i = numPackages - 1; i >= 0; i--) { 2310 final FullBackupEntry e = mFullBackupQueue.get(i); 2311 if (packageName.equals(e.packageName)) { 2312 mFullBackupQueue.remove(i); 2313 } 2314 } 2315 } 2316 2317 /** 2318 * Enqueue full backup for the given app, with a note about when it last ran. 2319 */ enqueueFullBackup(String packageName, long lastBackedUp)2320 public void enqueueFullBackup(String packageName, long lastBackedUp) { 2321 FullBackupEntry newEntry = new FullBackupEntry(packageName, lastBackedUp); 2322 synchronized (mQueueLock) { 2323 // First, check that we aren't adding a duplicate. Slow but 2324 // straightforward; we'll have at most on the order of a few hundred 2325 // items in this list. 2326 dequeueFullBackupLocked(packageName); 2327 2328 // This is also slow but easy for modest numbers of apps: work backwards 2329 // from the end of the queue until we find an item whose last backup 2330 // time was before this one, then insert this new entry after it. If we're 2331 // adding something new we don't bother scanning, and just prepend. 2332 int which = -1; 2333 if (lastBackedUp > 0) { 2334 for (which = mFullBackupQueue.size() - 1; which >= 0; which--) { 2335 final FullBackupEntry entry = mFullBackupQueue.get(which); 2336 if (entry.lastBackup <= lastBackedUp) { 2337 mFullBackupQueue.add(which + 1, newEntry); 2338 break; 2339 } 2340 } 2341 } 2342 if (which < 0) { 2343 // this one is earlier than any existing one, so prepend 2344 mFullBackupQueue.add(0, newEntry); 2345 } 2346 } 2347 writeFullBackupScheduleAsync(); 2348 } 2349 fullBackupAllowable(String transportName)2350 private boolean fullBackupAllowable(String transportName) { 2351 if (!mTransportManager.isTransportRegistered(transportName)) { 2352 Slog.w( 2353 TAG, 2354 addUserIdToLogMessage( 2355 mUserId, "Transport not registered; full data backup not performed")); 2356 return false; 2357 } 2358 2359 // Don't proceed unless we have already established package metadata 2360 // for the current dataset via a key/value backup pass. 2361 try { 2362 String transportDirName = mTransportManager.getTransportDirName(transportName); 2363 File stateDir = new File(mBaseStateDir, transportDirName); 2364 File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL); 2365 if (pmState.length() <= 0) { 2366 if (DEBUG) { 2367 Slog.i( 2368 TAG, 2369 addUserIdToLogMessage( 2370 mUserId, 2371 "Full backup requested but dataset not yet initialized")); 2372 } 2373 return false; 2374 } 2375 } catch (Exception e) { 2376 Slog.w( 2377 TAG, 2378 addUserIdToLogMessage( 2379 mUserId, "Unable to get transport name: " + e.getMessage())); 2380 return false; 2381 } 2382 2383 return true; 2384 } 2385 2386 /** 2387 * Conditions are right for a full backup operation, so run one. The model we use is 2388 * to perform one app backup per scheduled job execution, and to reschedule the job 2389 * with zero latency as long as conditions remain right and we still have work to do. 2390 * 2391 * <p>This is the "start a full backup operation" entry point called by the scheduled job. 2392 * 2393 * @return Whether ongoing work will continue. The return value here will be passed 2394 * along as the return value to the scheduled job's onStartJob() callback. 2395 */ beginFullBackup(FullBackupJob scheduledJob)2396 public boolean beginFullBackup(FullBackupJob scheduledJob) { 2397 final long now = System.currentTimeMillis(); 2398 final long fullBackupInterval; 2399 final long keyValueBackupInterval; 2400 synchronized (mConstants) { 2401 fullBackupInterval = mConstants.getFullBackupIntervalMilliseconds(); 2402 keyValueBackupInterval = mConstants.getKeyValueBackupIntervalMilliseconds(); 2403 } 2404 FullBackupEntry entry = null; 2405 long latency = fullBackupInterval; 2406 2407 if (!mEnabled || !mSetupComplete) { 2408 // Backups are globally disabled, so don't proceed. We also don't reschedule 2409 // the job driving automatic backups; that job will be scheduled again when 2410 // the user enables backup. 2411 if (MORE_DEBUG) { 2412 Slog.i(TAG, addUserIdToLogMessage(mUserId, "beginFullBackup but enabled=" + mEnabled 2413 + " setupComplete=" + mSetupComplete + "; ignoring")); 2414 } 2415 return false; 2416 } 2417 2418 // Don't run the backup if we're in battery saver mode, but reschedule 2419 // to try again in the not-so-distant future. 2420 final PowerSaveState result = 2421 mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP); 2422 if (result.batterySaverEnabled) { 2423 if (DEBUG) { 2424 Slog.i( 2425 TAG, 2426 addUserIdToLogMessage( 2427 mUserId, "Deferring scheduled full backups in battery saver mode")); 2428 } 2429 FullBackupJob.schedule(mUserId, mContext, keyValueBackupInterval, mConstants); 2430 return false; 2431 } 2432 2433 if (DEBUG_SCHEDULING) { 2434 Slog.i( 2435 TAG, 2436 addUserIdToLogMessage(mUserId, "Beginning scheduled full backup operation")); 2437 } 2438 2439 // Great; we're able to run full backup jobs now. See if we have any work to do. 2440 synchronized (mQueueLock) { 2441 if (mRunningFullBackupTask != null) { 2442 Slog.e( 2443 TAG, 2444 addUserIdToLogMessage( 2445 mUserId, "Backup triggered but one already/still running!")); 2446 return false; 2447 } 2448 2449 // At this point we think that we have work to do, but possibly not right now. 2450 // Any exit without actually running backups will also require that we 2451 // reschedule the job. 2452 boolean runBackup = true; 2453 boolean headBusy; 2454 2455 do { 2456 // Recheck each time, because culling due to ineligibility may 2457 // have emptied the queue. 2458 if (mFullBackupQueue.size() == 0) { 2459 // no work to do so just bow out 2460 if (DEBUG) { 2461 Slog.i( 2462 TAG, 2463 addUserIdToLogMessage( 2464 mUserId, "Backup queue empty; doing nothing")); 2465 } 2466 runBackup = false; 2467 break; 2468 } 2469 2470 headBusy = false; 2471 2472 String transportName = mTransportManager.getCurrentTransportName(); 2473 if (!fullBackupAllowable(transportName)) { 2474 if (MORE_DEBUG) { 2475 Slog.i( 2476 TAG, 2477 addUserIdToLogMessage( 2478 mUserId, "Preconditions not met; not running full backup")); 2479 } 2480 runBackup = false; 2481 // Typically this means we haven't run a key/value backup yet. Back off 2482 // full-backup operations by the key/value job's run interval so that 2483 // next time we run, we are likely to be able to make progress. 2484 latency = keyValueBackupInterval; 2485 } 2486 2487 if (runBackup) { 2488 entry = mFullBackupQueue.get(0); 2489 long timeSinceRun = now - entry.lastBackup; 2490 runBackup = (timeSinceRun >= fullBackupInterval); 2491 if (!runBackup) { 2492 // It's too early to back up the next thing in the queue, so bow out 2493 if (MORE_DEBUG) { 2494 Slog.i( 2495 TAG, 2496 addUserIdToLogMessage( 2497 mUserId, 2498 "Device ready but too early to back up next app")); 2499 } 2500 // Wait until the next app in the queue falls due for a full data backup 2501 latency = fullBackupInterval - timeSinceRun; 2502 break; // we know we aren't doing work yet, so bail. 2503 } 2504 2505 try { 2506 PackageInfo appInfo = mPackageManager.getPackageInfoAsUser( 2507 entry.packageName, 0, mUserId); 2508 if (!mScheduledBackupEligibility.appGetsFullBackup(appInfo)) { 2509 // The head app isn't supposed to get full-data backups [any more]; 2510 // so we cull it and force a loop around to consider the new head 2511 // app. 2512 if (MORE_DEBUG) { 2513 Slog.i( 2514 TAG, 2515 addUserIdToLogMessage( 2516 mUserId, 2517 "Culling package " 2518 + entry.packageName 2519 + " in full-backup queue but not" 2520 + " eligible")); 2521 } 2522 mFullBackupQueue.remove(0); 2523 headBusy = true; // force the while() condition 2524 continue; 2525 } 2526 2527 final int privFlags = appInfo.applicationInfo.privateFlags; 2528 headBusy = (privFlags & PRIVATE_FLAG_BACKUP_IN_FOREGROUND) == 0 2529 && mActivityManagerInternal.isAppForeground( 2530 appInfo.applicationInfo.uid); 2531 2532 if (headBusy) { 2533 final long nextEligible = System.currentTimeMillis() 2534 + BUSY_BACKOFF_MIN_MILLIS 2535 + mTokenGenerator.nextInt(BUSY_BACKOFF_FUZZ); 2536 if (DEBUG_SCHEDULING) { 2537 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 2538 Slog.i( 2539 TAG, 2540 addUserIdToLogMessage( 2541 mUserId, 2542 "Full backup time but " 2543 + entry.packageName 2544 + " is busy; deferring to " 2545 + sdf.format(new Date(nextEligible)))); 2546 } 2547 // This relocates the app's entry from the head of the queue to 2548 // its order-appropriate position further down, so upon looping 2549 // a new candidate will be considered at the head. 2550 enqueueFullBackup(entry.packageName, nextEligible - fullBackupInterval); 2551 } 2552 } catch (NameNotFoundException nnf) { 2553 // So, we think we want to back this up, but it turns out the package 2554 // in question is no longer installed. We want to drop it from the 2555 // queue entirely and move on, but if there's nothing else in the queue 2556 // we should bail entirely. headBusy cannot have been set to true yet. 2557 runBackup = (mFullBackupQueue.size() > 1); 2558 } 2559 } 2560 } while (headBusy); 2561 2562 if (!runBackup) { 2563 if (DEBUG_SCHEDULING) { 2564 Slog.i( 2565 TAG, 2566 addUserIdToLogMessage( 2567 mUserId, 2568 "Nothing pending full backup; rescheduling +" + latency)); 2569 } 2570 final long deferTime = latency; // pin for the closure 2571 FullBackupJob.schedule(mUserId, mContext, deferTime, mConstants); 2572 return false; 2573 } 2574 2575 // Okay, the top thing is ready for backup now. Do it. 2576 mFullBackupQueue.remove(0); 2577 CountDownLatch latch = new CountDownLatch(1); 2578 String[] pkg = new String[]{entry.packageName}; 2579 mRunningFullBackupTask = PerformFullTransportBackupTask.newWithCurrentTransport( 2580 this, 2581 /* observer */ null, 2582 pkg, 2583 /* updateSchedule */ true, 2584 scheduledJob, 2585 latch, 2586 /* backupObserver */ null, 2587 /* monitor */ null, 2588 /* userInitiated */ false, 2589 "BMS.beginFullBackup()", 2590 getEligibilityRulesForOperation(OperationType.BACKUP)); 2591 // Acquiring wakelock for PerformFullTransportBackupTask before its start. 2592 mWakelock.acquire(); 2593 (new Thread(mRunningFullBackupTask)).start(); 2594 } 2595 2596 return true; 2597 } 2598 2599 /** 2600 * The job scheduler says our constraints don't hold anymore, so tear down any ongoing backup 2601 * task right away. 2602 */ endFullBackup()2603 public void endFullBackup() { 2604 // offload the mRunningFullBackupTask.handleCancel() call to another thread, 2605 // as we might have to wait for mCancelLock 2606 Runnable endFullBackupRunnable = new Runnable() { 2607 @Override 2608 public void run() { 2609 PerformFullTransportBackupTask pftbt = null; 2610 synchronized (mQueueLock) { 2611 if (mRunningFullBackupTask != null) { 2612 pftbt = mRunningFullBackupTask; 2613 } 2614 } 2615 if (pftbt != null) { 2616 if (DEBUG_SCHEDULING) { 2617 Slog.i( 2618 TAG, 2619 addUserIdToLogMessage( 2620 mUserId, "Telling running backup to stop")); 2621 } 2622 pftbt.handleCancel(true); 2623 } 2624 } 2625 }; 2626 new Thread(endFullBackupRunnable, "end-full-backup").start(); 2627 } 2628 2629 /** Used by both incremental and full restore to restore widget data. */ restoreWidgetData(String packageName, byte[] widgetData)2630 public void restoreWidgetData(String packageName, byte[] widgetData) { 2631 // Apply the restored widget state and generate the ID update for the app 2632 if (MORE_DEBUG) { 2633 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Incorporating restored widget data")); 2634 } 2635 AppWidgetBackupBridge.restoreWidgetState(packageName, widgetData, mUserId); 2636 } 2637 2638 // ***************************** 2639 // NEW UNIFIED RESTORE IMPLEMENTATION 2640 // ***************************** 2641 2642 /** Schedule a backup pass for {@code packageName}. */ dataChangedImpl(String packageName)2643 public void dataChangedImpl(String packageName) { 2644 HashSet<String> targets = dataChangedTargets(packageName); 2645 dataChangedImpl(packageName, targets); 2646 } 2647 dataChangedImpl(String packageName, HashSet<String> targets)2648 private void dataChangedImpl(String packageName, HashSet<String> targets) { 2649 // Record that we need a backup pass for the caller. Since multiple callers 2650 // may share a uid, we need to note all candidates within that uid and schedule 2651 // a backup pass for each of them. 2652 if (targets == null) { 2653 Slog.w( 2654 TAG, 2655 addUserIdToLogMessage( 2656 mUserId, 2657 "dataChanged but no participant pkg='" 2658 + packageName 2659 + "'" 2660 + " uid=" 2661 + Binder.getCallingUid())); 2662 return; 2663 } 2664 2665 synchronized (mQueueLock) { 2666 // Note that this client has made data changes that need to be backed up 2667 if (targets.contains(packageName)) { 2668 // Add the caller to the set of pending backups. If there is 2669 // one already there, then overwrite it, but no harm done. 2670 BackupRequest req = new BackupRequest(packageName); 2671 if (mPendingBackups.put(packageName, req) == null) { 2672 if (MORE_DEBUG) { 2673 Slog.d( 2674 TAG, 2675 addUserIdToLogMessage( 2676 mUserId, "Now staging backup of " + packageName)); 2677 } 2678 2679 // Journal this request in case of crash. The put() 2680 // operation returned null when this package was not already 2681 // in the set; we want to avoid touching the disk redundantly. 2682 writeToJournalLocked(packageName); 2683 } 2684 } 2685 } 2686 2687 // ...and schedule a backup pass if necessary 2688 KeyValueBackupJob.schedule(mUserId, mContext, mConstants); 2689 } 2690 2691 // Note: packageName is currently unused, but may be in the future dataChangedTargets(String packageName)2692 private HashSet<String> dataChangedTargets(String packageName) { 2693 // If the caller does not hold the BACKUP permission, it can only request a 2694 // backup of its own data. 2695 if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(), 2696 Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) { 2697 synchronized (mBackupParticipants) { 2698 return mBackupParticipants.get(Binder.getCallingUid()); 2699 } 2700 } 2701 2702 // a caller with full permission can ask to back up any participating app 2703 if (PACKAGE_MANAGER_SENTINEL.equals(packageName)) { 2704 return Sets.newHashSet(PACKAGE_MANAGER_SENTINEL); 2705 } else { 2706 synchronized (mBackupParticipants) { 2707 return SparseArrayUtils.union(mBackupParticipants); 2708 } 2709 } 2710 } 2711 writeToJournalLocked(String str)2712 private void writeToJournalLocked(String str) { 2713 try { 2714 if (mJournal == null) mJournal = DataChangedJournal.newJournal(mJournalDir); 2715 mJournal.addPackage(str); 2716 } catch (IOException e) { 2717 Slog.e( 2718 TAG, 2719 addUserIdToLogMessage(mUserId, "Can't write " + str + " to backup journal"), 2720 e); 2721 mJournal = null; 2722 } 2723 } 2724 2725 // ----- IBackupManager binder interface ----- 2726 2727 /** Sent from an app's backup agent to let the service know that there's new data to backup. */ dataChanged(final String packageName)2728 public void dataChanged(final String packageName) { 2729 final HashSet<String> targets = dataChangedTargets(packageName); 2730 if (targets == null) { 2731 Slog.w( 2732 TAG, 2733 addUserIdToLogMessage( 2734 mUserId, 2735 "dataChanged but no participant pkg='" 2736 + packageName 2737 + "'" 2738 + " uid=" 2739 + Binder.getCallingUid())); 2740 return; 2741 } 2742 2743 mBackupHandler.post(new Runnable() { 2744 public void run() { 2745 dataChangedImpl(packageName, targets); 2746 } 2747 }); 2748 } 2749 2750 /** Run an initialize operation for the given transport. */ initializeTransports(String[] transportNames, IBackupObserver observer)2751 public void initializeTransports(String[] transportNames, IBackupObserver observer) { 2752 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 2753 "initializeTransport"); 2754 Slog.v( 2755 TAG, 2756 addUserIdToLogMessage( 2757 mUserId, "initializeTransport(): " + Arrays.asList(transportNames))); 2758 2759 final long oldId = Binder.clearCallingIdentity(); 2760 try { 2761 mWakelock.acquire(); 2762 OnTaskFinishedListener listener = caller -> mWakelock.release(); 2763 mBackupHandler.post( 2764 new PerformInitializeTask(this, transportNames, observer, listener)); 2765 } finally { 2766 Binder.restoreCallingIdentity(oldId); 2767 } 2768 } 2769 2770 /** 2771 * Sets the work profile serial number of the ancestral work profile. 2772 */ setAncestralSerialNumber(long ancestralSerialNumber)2773 public void setAncestralSerialNumber(long ancestralSerialNumber) { 2774 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, 2775 "setAncestralSerialNumber"); 2776 Slog.v( 2777 TAG, 2778 addUserIdToLogMessage( 2779 mUserId, "Setting ancestral work profile id to " + ancestralSerialNumber)); 2780 2781 try (RandomAccessFile af = 2782 new RandomAccessFile(getAncestralSerialNumberFile(), /* mode */ "rwd")) { 2783 af.writeLong(ancestralSerialNumber); 2784 } catch (IOException e) { 2785 Slog.w( 2786 TAG, 2787 addUserIdToLogMessage( 2788 mUserId, "Unable to write to work profile serial mapping file:"), 2789 e); 2790 } 2791 } 2792 2793 /** 2794 * Returns the work profile serial number of the ancestral device. This will be set by 2795 * {@link #setAncestralSerialNumber(long)}. Will return {@code -1} if not set. 2796 */ getAncestralSerialNumber()2797 public long getAncestralSerialNumber() { 2798 try (RandomAccessFile af = 2799 new RandomAccessFile(getAncestralSerialNumberFile(), /* mode */ "r")) { 2800 return af.readLong(); 2801 } catch (FileNotFoundException e) { 2802 // It's OK not to have the file present, so we just return -1 to indicate no value. 2803 } catch (IOException e) { 2804 Slog.w( 2805 TAG, 2806 addUserIdToLogMessage( 2807 mUserId, "Unable to read work profile serial number file:"), 2808 e); 2809 } 2810 return -1; 2811 } 2812 getAncestralSerialNumberFile()2813 private File getAncestralSerialNumberFile() { 2814 if (mAncestralSerialNumberFile == null) { 2815 mAncestralSerialNumberFile = new File( 2816 UserBackupManagerFiles.getBaseStateDir(getUserId()), 2817 SERIAL_ID_FILE); 2818 } 2819 return mAncestralSerialNumberFile; 2820 } 2821 2822 @VisibleForTesting setAncestralSerialNumberFile(File ancestralSerialNumberFile)2823 void setAncestralSerialNumberFile(File ancestralSerialNumberFile) { 2824 mAncestralSerialNumberFile = ancestralSerialNumberFile; 2825 } 2826 2827 2828 /** Clear the given package's backup data from the current transport. */ clearBackupData(String transportName, String packageName)2829 public void clearBackupData(String transportName, String packageName) { 2830 if (DEBUG) { 2831 Slog.v( 2832 TAG, 2833 addUserIdToLogMessage( 2834 mUserId, 2835 "clearBackupData() of " + packageName + " on " + transportName)); 2836 } 2837 2838 PackageInfo info; 2839 try { 2840 info = mPackageManager.getPackageInfoAsUser(packageName, 2841 PackageManager.GET_SIGNING_CERTIFICATES, mUserId); 2842 } catch (NameNotFoundException e) { 2843 Slog.d( 2844 TAG, 2845 addUserIdToLogMessage( 2846 mUserId, 2847 "No such package '" + packageName + "' - not clearing backup data")); 2848 return; 2849 } 2850 2851 // If the caller does not hold the BACKUP permission, it can only request a 2852 // wipe of its own backed-up data. 2853 Set<String> apps; 2854 if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(), 2855 Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) { 2856 apps = mBackupParticipants.get(Binder.getCallingUid()); 2857 } else { 2858 // a caller with full permission can ask to back up any participating app 2859 // !!! TODO: allow data-clear of ANY app? 2860 if (MORE_DEBUG) { 2861 Slog.v( 2862 TAG, 2863 addUserIdToLogMessage( 2864 mUserId, "Privileged caller, allowing clear of other apps")); 2865 } 2866 apps = mProcessedPackagesJournal.getPackagesCopy(); 2867 } 2868 2869 if (apps.contains(packageName)) { 2870 // found it; fire off the clear request 2871 if (MORE_DEBUG) { 2872 Slog.v( 2873 TAG, 2874 addUserIdToLogMessage(mUserId, "Found the app - running clear process")); 2875 } 2876 mBackupHandler.removeMessages(MSG_RETRY_CLEAR); 2877 synchronized (mQueueLock) { 2878 TransportClient transportClient = 2879 mTransportManager 2880 .getTransportClient(transportName, "BMS.clearBackupData()"); 2881 if (transportClient == null) { 2882 // transport is currently unregistered -- make sure to retry 2883 Message msg = mBackupHandler.obtainMessage(MSG_RETRY_CLEAR, 2884 new ClearRetryParams(transportName, packageName)); 2885 mBackupHandler.sendMessageDelayed(msg, TRANSPORT_RETRY_INTERVAL); 2886 return; 2887 } 2888 final long oldId = Binder.clearCallingIdentity(); 2889 try { 2890 OnTaskFinishedListener listener = caller -> mTransportManager 2891 .disposeOfTransportClient(transportClient, caller); 2892 mWakelock.acquire(); 2893 Message msg = mBackupHandler.obtainMessage( 2894 MSG_RUN_CLEAR, 2895 new ClearParams(transportClient, info, listener)); 2896 mBackupHandler.sendMessage(msg); 2897 } finally { 2898 Binder.restoreCallingIdentity(oldId); 2899 } 2900 } 2901 } 2902 } 2903 2904 /** 2905 * Run a backup pass immediately for any applications that have declared that they have pending 2906 * updates. 2907 */ backupNow()2908 public void backupNow() { 2909 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow"); 2910 2911 final long oldId = Binder.clearCallingIdentity(); 2912 try { 2913 final PowerSaveState result = 2914 mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP); 2915 if (result.batterySaverEnabled) { 2916 if (DEBUG) { 2917 Slog.v( 2918 TAG, 2919 addUserIdToLogMessage( 2920 mUserId, "Not running backup while in battery save mode")); 2921 } 2922 // Try again in several hours. 2923 KeyValueBackupJob.schedule(mUserId, mContext, mConstants); 2924 } else { 2925 if (DEBUG) { 2926 Slog.v(TAG, addUserIdToLogMessage(mUserId, "Scheduling immediate backup pass")); 2927 } 2928 2929 synchronized (getQueueLock()) { 2930 if (getPendingInits().size() > 0) { 2931 // If there are pending init operations, we process those and then settle 2932 // into the usual periodic backup schedule. 2933 if (MORE_DEBUG) { 2934 Slog.v( 2935 TAG, 2936 addUserIdToLogMessage( 2937 mUserId, "Init pending at scheduled backup")); 2938 } 2939 try { 2940 getAlarmManager().cancel(mRunInitIntent); 2941 mRunInitIntent.send(); 2942 } catch (PendingIntent.CanceledException ce) { 2943 Slog.w( 2944 TAG, 2945 addUserIdToLogMessage(mUserId, "Run init intent cancelled")); 2946 } 2947 return; 2948 } 2949 } 2950 2951 // Don't run backups if we're disabled or not yet set up. 2952 if (!isEnabled() || !isSetupComplete()) { 2953 Slog.w( 2954 TAG, 2955 addUserIdToLogMessage(mUserId, "Backup pass but enabled=" + isEnabled() 2956 + " setupComplete=" + isSetupComplete())); 2957 return; 2958 } 2959 2960 // Fire the msg that kicks off the whole shebang... 2961 Message message = mBackupHandler.obtainMessage(MSG_RUN_BACKUP); 2962 mBackupHandler.sendMessage(message); 2963 // ...and cancel any pending scheduled job, because we've just superseded it 2964 KeyValueBackupJob.cancel(mUserId, mContext); 2965 } 2966 } finally { 2967 Binder.restoreCallingIdentity(oldId); 2968 } 2969 } 2970 2971 /** 2972 * Used by 'adb backup' to run a backup pass for packages supplied via the command line, writing 2973 * the resulting data stream to the supplied {@code fd}. This method is synchronous and does not 2974 * return to the caller until the backup has been completed. It requires on-screen confirmation 2975 * by the user. 2976 */ adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, boolean doAllApps, boolean includeSystem, boolean compress, boolean doKeyValue, String[] pkgList)2977 public void adbBackup(ParcelFileDescriptor fd, boolean includeApks, 2978 boolean includeObbs, boolean includeShared, boolean doWidgets, boolean doAllApps, 2979 boolean includeSystem, boolean compress, boolean doKeyValue, String[] pkgList) { 2980 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbBackup"); 2981 2982 final int callingUserHandle = UserHandle.getCallingUserId(); 2983 if (callingUserHandle != UserHandle.USER_SYSTEM) { 2984 throw new IllegalStateException("Backup supported only for the device owner"); 2985 } 2986 2987 // Validate 2988 if (!doAllApps) { 2989 if (!includeShared) { 2990 // If we're backing up shared data (sdcard or equivalent), then we can run 2991 // without any supplied app names. Otherwise, we'd be doing no work, so 2992 // report the error. 2993 if (pkgList == null || pkgList.length == 0) { 2994 throw new IllegalArgumentException( 2995 "Backup requested but neither shared nor any apps named"); 2996 } 2997 } 2998 } 2999 3000 final long oldId = Binder.clearCallingIdentity(); 3001 try { 3002 if (!mSetupComplete) { 3003 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Backup not supported before setup")); 3004 return; 3005 } 3006 3007 if (DEBUG) { 3008 Slog.v( 3009 TAG, 3010 addUserIdToLogMessage( 3011 mUserId, 3012 "Requesting backup: apks=" 3013 + includeApks 3014 + " obb=" 3015 + includeObbs 3016 + " shared=" 3017 + includeShared 3018 + " all=" 3019 + doAllApps 3020 + " system=" 3021 + includeSystem 3022 + " includekeyvalue=" 3023 + doKeyValue 3024 + " pkgs=" 3025 + pkgList)); 3026 } 3027 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Beginning adb backup...")); 3028 3029 BackupEligibilityRules eligibilityRules = getEligibilityRulesForOperation( 3030 OperationType.ADB_BACKUP); 3031 AdbBackupParams params = new AdbBackupParams(fd, includeApks, includeObbs, 3032 includeShared, doWidgets, doAllApps, includeSystem, compress, doKeyValue, 3033 pkgList, eligibilityRules); 3034 final int token = generateRandomIntegerToken(); 3035 synchronized (mAdbBackupRestoreConfirmations) { 3036 mAdbBackupRestoreConfirmations.put(token, params); 3037 } 3038 3039 // start up the confirmation UI 3040 if (DEBUG) { 3041 Slog.d( 3042 TAG, 3043 addUserIdToLogMessage( 3044 mUserId, "Starting backup confirmation UI, token=" + token)); 3045 } 3046 if (!startConfirmationUi(token, FullBackup.FULL_BACKUP_INTENT_ACTION)) { 3047 Slog.e( 3048 TAG, 3049 addUserIdToLogMessage(mUserId, "Unable to launch backup confirmation UI")); 3050 mAdbBackupRestoreConfirmations.delete(token); 3051 return; 3052 } 3053 3054 // make sure the screen is lit for the user interaction 3055 mPowerManager.userActivity(SystemClock.uptimeMillis(), 3056 PowerManager.USER_ACTIVITY_EVENT_OTHER, 3057 0); 3058 3059 // start the confirmation countdown 3060 startConfirmationTimeout(token, params); 3061 3062 // wait for the backup to be performed 3063 if (DEBUG) { 3064 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Waiting for backup completion...")); 3065 } 3066 waitForCompletion(params); 3067 } finally { 3068 try { 3069 fd.close(); 3070 } catch (IOException e) { 3071 Slog.e( 3072 TAG, 3073 addUserIdToLogMessage( 3074 mUserId, 3075 "IO error closing output for adb backup: " + e.getMessage())); 3076 } 3077 Binder.restoreCallingIdentity(oldId); 3078 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Adb backup processing complete.")); 3079 } 3080 } 3081 3082 /** Run a full backup pass for the given packages. Used by 'adb shell bmgr'. */ fullTransportBackup(String[] pkgNames)3083 public void fullTransportBackup(String[] pkgNames) { 3084 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, 3085 "fullTransportBackup"); 3086 3087 final int callingUserHandle = UserHandle.getCallingUserId(); 3088 // TODO: http://b/22388012 3089 if (callingUserHandle != UserHandle.USER_SYSTEM) { 3090 throw new IllegalStateException("Restore supported only for the device owner"); 3091 } 3092 3093 String transportName = mTransportManager.getCurrentTransportName(); 3094 if (!fullBackupAllowable(transportName)) { 3095 Slog.i( 3096 TAG, 3097 addUserIdToLogMessage( 3098 mUserId, 3099 "Full backup not currently possible -- key/value backup not yet run?")); 3100 } else { 3101 if (DEBUG) { 3102 Slog.d(TAG, addUserIdToLogMessage(mUserId, "fullTransportBackup()")); 3103 } 3104 3105 final long oldId = Binder.clearCallingIdentity(); 3106 try { 3107 CountDownLatch latch = new CountDownLatch(1); 3108 Runnable task = PerformFullTransportBackupTask.newWithCurrentTransport( 3109 this, 3110 /* observer */ null, 3111 pkgNames, 3112 /* updateSchedule */ false, 3113 /* runningJob */ null, 3114 latch, 3115 /* backupObserver */ null, 3116 /* monitor */ null, 3117 /* userInitiated */ false, 3118 "BMS.fullTransportBackup()", 3119 getEligibilityRulesForOperation(OperationType.BACKUP)); 3120 // Acquiring wakelock for PerformFullTransportBackupTask before its start. 3121 mWakelock.acquire(); 3122 (new Thread(task, "full-transport-master")).start(); 3123 do { 3124 try { 3125 latch.await(); 3126 break; 3127 } catch (InterruptedException e) { 3128 // Just go back to waiting for the latch to indicate completion 3129 } 3130 } while (true); 3131 3132 // We just ran a backup on these packages, so kick them to the end of the queue 3133 final long now = System.currentTimeMillis(); 3134 for (String pkg : pkgNames) { 3135 enqueueFullBackup(pkg, now); 3136 } 3137 } finally { 3138 Binder.restoreCallingIdentity(oldId); 3139 } 3140 } 3141 3142 if (DEBUG) { 3143 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Done with full transport backup.")); 3144 } 3145 } 3146 3147 /** 3148 * Used by 'adb restore' to run a restore pass, blocking until completion. Requires user 3149 * confirmation. 3150 */ adbRestore(ParcelFileDescriptor fd)3151 public void adbRestore(ParcelFileDescriptor fd) { 3152 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbRestore"); 3153 3154 final int callingUserHandle = UserHandle.getCallingUserId(); 3155 if (callingUserHandle != UserHandle.USER_SYSTEM) { 3156 throw new IllegalStateException("Restore supported only for the device owner"); 3157 } 3158 3159 final long oldId = Binder.clearCallingIdentity(); 3160 3161 try { 3162 if (!mSetupComplete) { 3163 Slog.i( 3164 TAG, 3165 addUserIdToLogMessage(mUserId, "Full restore not permitted before setup")); 3166 return; 3167 } 3168 3169 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Beginning restore...")); 3170 3171 AdbRestoreParams params = new AdbRestoreParams(fd); 3172 final int token = generateRandomIntegerToken(); 3173 synchronized (mAdbBackupRestoreConfirmations) { 3174 mAdbBackupRestoreConfirmations.put(token, params); 3175 } 3176 3177 // start up the confirmation UI 3178 if (DEBUG) { 3179 Slog.d( 3180 TAG, 3181 addUserIdToLogMessage( 3182 mUserId, "Starting restore confirmation UI, token=" + token)); 3183 } 3184 if (!startConfirmationUi(token, FullBackup.FULL_RESTORE_INTENT_ACTION)) { 3185 Slog.e( 3186 TAG, 3187 addUserIdToLogMessage(mUserId, "Unable to launch restore confirmation")); 3188 mAdbBackupRestoreConfirmations.delete(token); 3189 return; 3190 } 3191 3192 // make sure the screen is lit for the user interaction 3193 mPowerManager.userActivity(SystemClock.uptimeMillis(), 3194 PowerManager.USER_ACTIVITY_EVENT_OTHER, 3195 0); 3196 3197 // start the confirmation countdown 3198 startConfirmationTimeout(token, params); 3199 3200 // wait for the restore to be performed 3201 if (DEBUG) { 3202 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Waiting for restore completion...")); 3203 } 3204 waitForCompletion(params); 3205 } finally { 3206 try { 3207 fd.close(); 3208 } catch (IOException e) { 3209 Slog.w( 3210 TAG, 3211 addUserIdToLogMessage( 3212 mUserId, "Error trying to close fd after adb restore: " + e)); 3213 } 3214 Binder.restoreCallingIdentity(oldId); 3215 Slog.i(TAG, addUserIdToLogMessage(mUserId, "adb restore processing complete.")); 3216 } 3217 } 3218 3219 /** 3220 * Excludes keys from KV restore for a given package. The keys won't be part of the data passed 3221 * to the backup agent during restore. 3222 */ excludeKeysFromRestore(String packageName, List<String> keys)3223 public void excludeKeysFromRestore(String packageName, List<String> keys) { 3224 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3225 "excludeKeysFromRestore"); 3226 mBackupPreferences.addExcludedKeys(packageName, keys); 3227 } 3228 startConfirmationUi(int token, String action)3229 private boolean startConfirmationUi(int token, String action) { 3230 try { 3231 Intent confIntent = new Intent(action); 3232 confIntent.setClassName("com.android.backupconfirm", 3233 "com.android.backupconfirm.BackupRestoreConfirmation"); 3234 confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token); 3235 confIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 3236 mContext.startActivityAsUser(confIntent, UserHandle.SYSTEM); 3237 } catch (ActivityNotFoundException e) { 3238 return false; 3239 } 3240 return true; 3241 } 3242 startConfirmationTimeout(int token, AdbParams params)3243 private void startConfirmationTimeout(int token, AdbParams params) { 3244 if (MORE_DEBUG) { 3245 Slog.d(TAG, addUserIdToLogMessage(mUserId, "Posting conf timeout msg after " 3246 + TIMEOUT_FULL_CONFIRMATION + " millis")); 3247 } 3248 Message msg = mBackupHandler.obtainMessage(MSG_FULL_CONFIRMATION_TIMEOUT, 3249 token, 0, params); 3250 mBackupHandler.sendMessageDelayed(msg, TIMEOUT_FULL_CONFIRMATION); 3251 } 3252 waitForCompletion(AdbParams params)3253 private void waitForCompletion(AdbParams params) { 3254 synchronized (params.latch) { 3255 while (!params.latch.get()) { 3256 try { 3257 params.latch.wait(); 3258 } catch (InterruptedException e) { /* never interrupted */ } 3259 } 3260 } 3261 } 3262 3263 /** Called when adb backup/restore has completed. */ signalAdbBackupRestoreCompletion(AdbParams params)3264 public void signalAdbBackupRestoreCompletion(AdbParams params) { 3265 synchronized (params.latch) { 3266 params.latch.set(true); 3267 params.latch.notifyAll(); 3268 } 3269 } 3270 3271 /** 3272 * Confirm that the previously-requested full backup/restore operation can proceed. This is used 3273 * to require a user-facing disclosure about the operation. 3274 */ acknowledgeAdbBackupOrRestore(int token, boolean allow, String curPassword, String encPpassword, IFullBackupRestoreObserver observer)3275 public void acknowledgeAdbBackupOrRestore(int token, boolean allow, 3276 String curPassword, String encPpassword, IFullBackupRestoreObserver observer) { 3277 if (DEBUG) { 3278 Slog.d( 3279 TAG, 3280 addUserIdToLogMessage( 3281 mUserId, 3282 "acknowledgeAdbBackupOrRestore : token=" + token + " allow=" + allow)); 3283 } 3284 3285 // TODO: possibly require not just this signature-only permission, but even 3286 // require that the specific designated confirmation-UI app uid is the caller? 3287 mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, 3288 "acknowledgeAdbBackupOrRestore"); 3289 3290 final long oldId = Binder.clearCallingIdentity(); 3291 try { 3292 3293 AdbParams params; 3294 synchronized (mAdbBackupRestoreConfirmations) { 3295 params = mAdbBackupRestoreConfirmations.get(token); 3296 if (params != null) { 3297 mBackupHandler.removeMessages(MSG_FULL_CONFIRMATION_TIMEOUT, params); 3298 mAdbBackupRestoreConfirmations.delete(token); 3299 3300 if (allow) { 3301 final int verb = params instanceof AdbBackupParams 3302 ? MSG_RUN_ADB_BACKUP 3303 : MSG_RUN_ADB_RESTORE; 3304 3305 params.observer = observer; 3306 params.curPassword = curPassword; 3307 3308 params.encryptPassword = encPpassword; 3309 3310 if (MORE_DEBUG) { 3311 Slog.d( 3312 TAG, 3313 addUserIdToLogMessage( 3314 mUserId, "Sending conf message with verb " + verb)); 3315 } 3316 mWakelock.acquire(); 3317 Message msg = mBackupHandler.obtainMessage(verb, params); 3318 mBackupHandler.sendMessage(msg); 3319 } else { 3320 Slog.w( 3321 TAG, 3322 addUserIdToLogMessage( 3323 mUserId, "User rejected full backup/restore operation")); 3324 // indicate completion without having actually transferred any data 3325 signalAdbBackupRestoreCompletion(params); 3326 } 3327 } else { 3328 Slog.w( 3329 TAG, 3330 addUserIdToLogMessage( 3331 mUserId, 3332 "Attempted to ack full backup/restore with invalid token")); 3333 } 3334 } 3335 } finally { 3336 Binder.restoreCallingIdentity(oldId); 3337 } 3338 } 3339 3340 /** User-configurable enabling/disabling of backups. */ setBackupEnabled(boolean enable)3341 public void setBackupEnabled(boolean enable) { 3342 setBackupEnabled(enable, /* persistToDisk */ true); 3343 } 3344 setBackupEnabled(boolean enable, boolean persistToDisk)3345 private void setBackupEnabled(boolean enable, boolean persistToDisk) { 3346 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3347 "setBackupEnabled"); 3348 3349 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Backup enabled => " + enable)); 3350 3351 final long oldId = Binder.clearCallingIdentity(); 3352 try { 3353 boolean wasEnabled = mEnabled; 3354 synchronized (this) { 3355 if (persistToDisk) { 3356 writeEnabledState(enable); 3357 } 3358 mEnabled = enable; 3359 } 3360 3361 updateStateOnBackupEnabled(wasEnabled, enable); 3362 } finally { 3363 Binder.restoreCallingIdentity(oldId); 3364 } 3365 } 3366 3367 @VisibleForTesting updateStateOnBackupEnabled(boolean wasEnabled, boolean enable)3368 void updateStateOnBackupEnabled(boolean wasEnabled, boolean enable) { 3369 synchronized (mQueueLock) { 3370 if (enable && !wasEnabled && mSetupComplete) { 3371 // if we've just been enabled, start scheduling backup passes 3372 KeyValueBackupJob.schedule(mUserId, mContext, mConstants); 3373 scheduleNextFullBackupJob(0); 3374 } else if (!enable) { 3375 // No longer enabled, so stop running backups 3376 if (MORE_DEBUG) { 3377 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Opting out of backup")); 3378 } 3379 3380 KeyValueBackupJob.cancel(mUserId, mContext); 3381 3382 // This also constitutes an opt-out, so we wipe any data for 3383 // this device from the backend. We start that process with 3384 // an alarm in order to guarantee wakelock states. 3385 if (wasEnabled && mSetupComplete) { 3386 // NOTE: we currently flush every registered transport, not just 3387 // the currently-active one. 3388 List<String> transportNames = new ArrayList<>(); 3389 List<String> transportDirNames = new ArrayList<>(); 3390 mTransportManager.forEachRegisteredTransport( 3391 name -> { 3392 final String dirName; 3393 try { 3394 dirName = mTransportManager.getTransportDirName(name); 3395 } catch (TransportNotRegisteredException e) { 3396 // Should never happen 3397 Slog.e( 3398 TAG, 3399 addUserIdToLogMessage( 3400 mUserId, "Unexpected unregistered transport"), 3401 e); 3402 return; 3403 } 3404 transportNames.add(name); 3405 transportDirNames.add(dirName); 3406 }); 3407 3408 // build the set of transports for which we are posting an init 3409 for (int i = 0; i < transportNames.size(); i++) { 3410 recordInitPending( 3411 true, 3412 transportNames.get(i), 3413 transportDirNames.get(i)); 3414 } 3415 mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 3416 mRunInitIntent); 3417 } 3418 } 3419 } 3420 } 3421 3422 @VisibleForTesting writeEnabledState(boolean enable)3423 void writeEnabledState(boolean enable) { 3424 UserBackupManagerFilePersistedSettings.writeBackupEnableState(mUserId, enable); 3425 } 3426 3427 @VisibleForTesting readEnabledState()3428 boolean readEnabledState() { 3429 return UserBackupManagerFilePersistedSettings.readBackupEnableState(mUserId); 3430 } 3431 3432 /** Enable/disable automatic restore of app data at install time. */ setAutoRestore(boolean doAutoRestore)3433 public void setAutoRestore(boolean doAutoRestore) { 3434 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3435 "setAutoRestore"); 3436 3437 Slog.i(TAG, addUserIdToLogMessage(mUserId, "Auto restore => " + doAutoRestore)); 3438 3439 final long oldId = Binder.clearCallingIdentity(); 3440 try { 3441 synchronized (this) { 3442 Settings.Secure.putIntForUser(mContext.getContentResolver(), 3443 Settings.Secure.BACKUP_AUTO_RESTORE, doAutoRestore ? 1 : 0, mUserId); 3444 mAutoRestore = doAutoRestore; 3445 } 3446 } finally { 3447 Binder.restoreCallingIdentity(oldId); 3448 } 3449 } 3450 3451 /** Report whether the backup mechanism is currently enabled. */ isBackupEnabled()3452 public boolean isBackupEnabled() { 3453 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3454 "isBackupEnabled"); 3455 return mEnabled; // no need to synchronize just to read it 3456 } 3457 3458 /** Report the name of the currently active transport. */ getCurrentTransport()3459 public String getCurrentTransport() { 3460 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3461 "getCurrentTransport"); 3462 String currentTransport = mTransportManager.getCurrentTransportName(); 3463 if (MORE_DEBUG) { 3464 Slog.v( 3465 TAG, 3466 addUserIdToLogMessage( 3467 mUserId, "... getCurrentTransport() returning " + currentTransport)); 3468 } 3469 return currentTransport; 3470 } 3471 3472 /** 3473 * Returns the {@link ComponentName} of the host service of the selected transport or {@code 3474 * null} if no transport selected or if the transport selected is not registered. 3475 */ 3476 @Nullable getCurrentTransportComponent()3477 public ComponentName getCurrentTransportComponent() { 3478 mContext.enforceCallingOrSelfPermission( 3479 android.Manifest.permission.BACKUP, "getCurrentTransportComponent"); 3480 final long oldId = Binder.clearCallingIdentity(); 3481 try { 3482 return mTransportManager.getCurrentTransportComponent(); 3483 } catch (TransportNotRegisteredException e) { 3484 return null; 3485 } finally { 3486 Binder.restoreCallingIdentity(oldId); 3487 } 3488 } 3489 3490 /** Report all known, available backup transports by name. */ listAllTransports()3491 public String[] listAllTransports() { 3492 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3493 "listAllTransports"); 3494 3495 return mTransportManager.getRegisteredTransportNames(); 3496 } 3497 3498 /** Report all known, available backup transports by component. */ listAllTransportComponents()3499 public ComponentName[] listAllTransportComponents() { 3500 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3501 "listAllTransportComponents"); 3502 return mTransportManager.getRegisteredTransportComponents(); 3503 } 3504 3505 /** 3506 * Update the attributes of the transport identified by {@code transportComponent}. If the 3507 * specified transport has not been bound at least once (for registration), this call will be 3508 * ignored. Only the host process of the transport can change its description, otherwise a 3509 * {@link SecurityException} will be thrown. 3510 * 3511 * @param transportComponent The identity of the transport being described. 3512 * @param name A {@link String} with the new name for the transport. This is NOT for 3513 * identification. MUST NOT be {@code null}. 3514 * @param configurationIntent An {@link Intent} that can be passed to 3515 * {@link Context#startActivity} in order to launch the transport's configuration UI. It may 3516 * be {@code null} if the transport does not offer any user-facing configuration UI. 3517 * @param currentDestinationString A {@link String} describing the destination to which the 3518 * transport is currently sending data. MUST NOT be {@code null}. 3519 * @param dataManagementIntent An {@link Intent} that can be passed to 3520 * {@link Context#startActivity} in order to launch the transport's data-management UI. It 3521 * may be {@code null} if the transport does not offer any user-facing data 3522 * management UI. 3523 * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's 3524 * data management affordance. This MUST be {@code null} when dataManagementIntent is 3525 * {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. 3526 * @throws SecurityException If the UID of the calling process differs from the package UID of 3527 * {@code transportComponent} or if the caller does NOT have BACKUP permission. 3528 */ updateTransportAttributes( ComponentName transportComponent, String name, @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, @Nullable CharSequence dataManagementLabel)3529 public void updateTransportAttributes( 3530 ComponentName transportComponent, 3531 String name, 3532 @Nullable Intent configurationIntent, 3533 String currentDestinationString, 3534 @Nullable Intent dataManagementIntent, 3535 @Nullable CharSequence dataManagementLabel) { 3536 updateTransportAttributes( 3537 Binder.getCallingUid(), 3538 transportComponent, 3539 name, 3540 configurationIntent, 3541 currentDestinationString, 3542 dataManagementIntent, 3543 dataManagementLabel); 3544 } 3545 3546 @VisibleForTesting updateTransportAttributes( int callingUid, ComponentName transportComponent, String name, @Nullable Intent configurationIntent, String currentDestinationString, @Nullable Intent dataManagementIntent, @Nullable CharSequence dataManagementLabel)3547 void updateTransportAttributes( 3548 int callingUid, 3549 ComponentName transportComponent, 3550 String name, 3551 @Nullable Intent configurationIntent, 3552 String currentDestinationString, 3553 @Nullable Intent dataManagementIntent, 3554 @Nullable CharSequence dataManagementLabel) { 3555 mContext.enforceCallingOrSelfPermission( 3556 android.Manifest.permission.BACKUP, "updateTransportAttributes"); 3557 3558 Objects.requireNonNull(transportComponent, "transportComponent can't be null"); 3559 Objects.requireNonNull(name, "name can't be null"); 3560 Objects.requireNonNull( 3561 currentDestinationString, "currentDestinationString can't be null"); 3562 Preconditions.checkArgument( 3563 (dataManagementIntent == null) == (dataManagementLabel == null), 3564 "dataManagementLabel should be null iff dataManagementIntent is null"); 3565 3566 try { 3567 int transportUid = 3568 mContext.getPackageManager() 3569 .getPackageUidAsUser(transportComponent.getPackageName(), 0, mUserId); 3570 if (callingUid != transportUid) { 3571 throw new SecurityException("Only the transport can change its description"); 3572 } 3573 } catch (NameNotFoundException e) { 3574 throw new SecurityException("Transport package not found", e); 3575 } 3576 3577 final long oldId = Binder.clearCallingIdentity(); 3578 try { 3579 mTransportManager.updateTransportAttributes( 3580 transportComponent, 3581 name, 3582 configurationIntent, 3583 currentDestinationString, 3584 dataManagementIntent, 3585 dataManagementLabel); 3586 } finally { 3587 Binder.restoreCallingIdentity(oldId); 3588 } 3589 } 3590 3591 /** 3592 * Selects transport {@code transportName} and returns previously selected transport. 3593 * 3594 * @deprecated Use {@link #selectBackupTransportAsync(ComponentName, 3595 * ISelectBackupTransportCallback)} instead. 3596 */ 3597 @Deprecated 3598 @Nullable selectBackupTransport(String transportName)3599 public String selectBackupTransport(String transportName) { 3600 mContext.enforceCallingOrSelfPermission( 3601 android.Manifest.permission.BACKUP, "selectBackupTransport"); 3602 3603 final long oldId = Binder.clearCallingIdentity(); 3604 try { 3605 String previousTransportName = mTransportManager.selectTransport(transportName); 3606 updateStateForTransport(transportName); 3607 Slog.v( 3608 TAG, 3609 addUserIdToLogMessage( 3610 mUserId, 3611 "selectBackupTransport(transport = " 3612 + transportName 3613 + "): previous transport = " 3614 + previousTransportName)); 3615 return previousTransportName; 3616 } finally { 3617 Binder.restoreCallingIdentity(oldId); 3618 } 3619 } 3620 3621 /** 3622 * Selects transport {@code transportComponent} asynchronously and notifies {@code listener} 3623 * with the result upon completion. 3624 */ selectBackupTransportAsync( ComponentName transportComponent, ISelectBackupTransportCallback listener)3625 public void selectBackupTransportAsync( 3626 ComponentName transportComponent, ISelectBackupTransportCallback listener) { 3627 mContext.enforceCallingOrSelfPermission( 3628 android.Manifest.permission.BACKUP, "selectBackupTransportAsync"); 3629 3630 final long oldId = Binder.clearCallingIdentity(); 3631 try { 3632 String transportString = transportComponent.flattenToShortString(); 3633 Slog.v( 3634 TAG, 3635 addUserIdToLogMessage( 3636 mUserId, 3637 "selectBackupTransportAsync(transport = " + transportString + ")")); 3638 mBackupHandler.post( 3639 () -> { 3640 String transportName = null; 3641 int result = 3642 mTransportManager.registerAndSelectTransport(transportComponent); 3643 if (result == BackupManager.SUCCESS) { 3644 try { 3645 transportName = 3646 mTransportManager.getTransportName(transportComponent); 3647 updateStateForTransport(transportName); 3648 } catch (TransportNotRegisteredException e) { 3649 Slog.e( 3650 TAG, 3651 addUserIdToLogMessage( 3652 mUserId, "Transport got unregistered")); 3653 result = BackupManager.ERROR_TRANSPORT_UNAVAILABLE; 3654 } 3655 } 3656 3657 try { 3658 if (transportName != null) { 3659 listener.onSuccess(transportName); 3660 } else { 3661 listener.onFailure(result); 3662 } 3663 } catch (RemoteException e) { 3664 Slog.e( 3665 TAG, 3666 addUserIdToLogMessage( 3667 mUserId, 3668 "ISelectBackupTransportCallback listener not" 3669 + " available")); 3670 } 3671 }); 3672 } finally { 3673 Binder.restoreCallingIdentity(oldId); 3674 } 3675 } 3676 3677 /** 3678 * We want to skip backup/restore of certain packages if 'backup_skip_user_facing_packages' is 3679 * set to true in secure settings. See b/153940088 for details. 3680 * 3681 * TODO(b/154822946): Remove this logic in the next release. 3682 */ filterUserFacingPackages(List<PackageInfo> packages)3683 public List<PackageInfo> filterUserFacingPackages(List<PackageInfo> packages) { 3684 if (!shouldSkipUserFacingData()) { 3685 return packages; 3686 } 3687 3688 List<PackageInfo> filteredPackages = new ArrayList<>(packages.size()); 3689 for (PackageInfo packageInfo : packages) { 3690 if (!shouldSkipPackage(packageInfo.packageName)) { 3691 filteredPackages.add(packageInfo); 3692 } else { 3693 Slog.i(TAG, "Will skip backup/restore for " + packageInfo.packageName); 3694 } 3695 } 3696 3697 return filteredPackages; 3698 } 3699 3700 @VisibleForTesting shouldSkipUserFacingData()3701 public boolean shouldSkipUserFacingData() { 3702 return Settings.Secure.getInt(mContext.getContentResolver(), SKIP_USER_FACING_PACKAGES, 3703 /* def */ 0) != 0; 3704 } 3705 3706 @VisibleForTesting shouldSkipPackage(String packageName)3707 public boolean shouldSkipPackage(String packageName) { 3708 return WALLPAPER_PACKAGE.equals(packageName); 3709 } 3710 updateStateForTransport(String newTransportName)3711 private void updateStateForTransport(String newTransportName) { 3712 // Publish the name change 3713 Settings.Secure.putStringForUser(mContext.getContentResolver(), 3714 Settings.Secure.BACKUP_TRANSPORT, newTransportName, mUserId); 3715 3716 // And update our current-dataset bookkeeping 3717 String callerLogString = "BMS.updateStateForTransport()"; 3718 TransportClient transportClient = 3719 mTransportManager.getTransportClient(newTransportName, callerLogString); 3720 if (transportClient != null) { 3721 try { 3722 IBackupTransport transport = transportClient.connectOrThrow(callerLogString); 3723 mCurrentToken = transport.getCurrentRestoreSet(); 3724 } catch (Exception e) { 3725 // Oops. We can't know the current dataset token, so reset and figure it out 3726 // when we do the next k/v backup operation on this transport. 3727 mCurrentToken = 0; 3728 Slog.w( 3729 TAG, 3730 addUserIdToLogMessage( 3731 mUserId, 3732 "Transport " 3733 + newTransportName 3734 + " not available: current token = 0")); 3735 } 3736 mTransportManager.disposeOfTransportClient(transportClient, callerLogString); 3737 } else { 3738 Slog.w( 3739 TAG, 3740 addUserIdToLogMessage( 3741 mUserId, 3742 "Transport " 3743 + newTransportName 3744 + " not registered: current token = 0")); 3745 // The named transport isn't registered, so we can't know what its current dataset token 3746 // is. Reset as above. 3747 mCurrentToken = 0; 3748 } 3749 } 3750 3751 /** 3752 * Supply the configuration intent for the given transport. If the name is not one of the 3753 * available transports, or if the transport does not supply any configuration UI, the method 3754 * returns {@code null}. 3755 */ getConfigurationIntent(String transportName)3756 public Intent getConfigurationIntent(String transportName) { 3757 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3758 "getConfigurationIntent"); 3759 try { 3760 Intent intent = mTransportManager.getTransportConfigurationIntent(transportName); 3761 if (MORE_DEBUG) { 3762 Slog.d( 3763 TAG, 3764 addUserIdToLogMessage( 3765 mUserId, "getConfigurationIntent() returning intent " + intent)); 3766 } 3767 return intent; 3768 } catch (TransportNotRegisteredException e) { 3769 Slog.e( 3770 TAG, 3771 addUserIdToLogMessage( 3772 mUserId, 3773 "Unable to get configuration intent from transport: " 3774 + e.getMessage())); 3775 return null; 3776 } 3777 } 3778 3779 /** 3780 * Supply the current destination string for the given transport. If the name is not one of the 3781 * registered transports the method will return null. 3782 * 3783 * <p>This string is used VERBATIM as the summary text of the relevant Settings item. 3784 * 3785 * @param transportName The name of the registered transport. 3786 * @return The current destination string or null if the transport is not registered. 3787 */ getDestinationString(String transportName)3788 public String getDestinationString(String transportName) { 3789 mContext.enforceCallingOrSelfPermission( 3790 android.Manifest.permission.BACKUP, "getDestinationString"); 3791 3792 try { 3793 String string = mTransportManager.getTransportCurrentDestinationString(transportName); 3794 if (MORE_DEBUG) { 3795 Slog.d( 3796 TAG, 3797 addUserIdToLogMessage( 3798 mUserId, "getDestinationString() returning " + string)); 3799 } 3800 return string; 3801 } catch (TransportNotRegisteredException e) { 3802 Slog.e( 3803 TAG, 3804 addUserIdToLogMessage( 3805 mUserId, 3806 "Unable to get destination string from transport: " + e.getMessage())); 3807 return null; 3808 } 3809 } 3810 3811 /** Supply the manage-data intent for the given transport. */ getDataManagementIntent(String transportName)3812 public Intent getDataManagementIntent(String transportName) { 3813 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3814 "getDataManagementIntent"); 3815 3816 try { 3817 Intent intent = mTransportManager.getTransportDataManagementIntent(transportName); 3818 if (MORE_DEBUG) { 3819 Slog.d( 3820 TAG, 3821 addUserIdToLogMessage( 3822 mUserId, "getDataManagementIntent() returning intent " + intent)); 3823 } 3824 return intent; 3825 } catch (TransportNotRegisteredException e) { 3826 Slog.e( 3827 TAG, 3828 addUserIdToLogMessage( 3829 mUserId, 3830 "Unable to get management intent from transport: " + e.getMessage())); 3831 return null; 3832 } 3833 } 3834 3835 /** 3836 * Supply the menu label for affordances that fire the manage-data intent for the given 3837 * transport. 3838 */ getDataManagementLabel(String transportName)3839 public CharSequence getDataManagementLabel(String transportName) { 3840 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 3841 "getDataManagementLabel"); 3842 3843 try { 3844 CharSequence label = mTransportManager.getTransportDataManagementLabel(transportName); 3845 if (MORE_DEBUG) { 3846 Slog.d( 3847 TAG, 3848 addUserIdToLogMessage( 3849 mUserId, "getDataManagementLabel() returning " + label)); 3850 } 3851 return label; 3852 } catch (TransportNotRegisteredException e) { 3853 Slog.e( 3854 TAG, 3855 addUserIdToLogMessage( 3856 mUserId, 3857 "Unable to get management label from transport: " + e.getMessage())); 3858 return null; 3859 } 3860 } 3861 3862 /** 3863 * Callback: a requested backup agent has been instantiated. This should only be called from the 3864 * {@link ActivityManager}. 3865 */ agentConnected(String packageName, IBinder agentBinder)3866 public void agentConnected(String packageName, IBinder agentBinder) { 3867 synchronized (mAgentConnectLock) { 3868 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 3869 Slog.d( 3870 TAG, 3871 addUserIdToLogMessage( 3872 mUserId, 3873 "agentConnected pkg=" + packageName + " agent=" + agentBinder)); 3874 mConnectedAgent = IBackupAgent.Stub.asInterface(agentBinder); 3875 mConnecting = false; 3876 } else { 3877 Slog.w( 3878 TAG, 3879 addUserIdToLogMessage( 3880 mUserId, 3881 "Non-system process uid=" 3882 + Binder.getCallingUid() 3883 + " claiming agent connected")); 3884 } 3885 mAgentConnectLock.notifyAll(); 3886 } 3887 } 3888 3889 /** 3890 * Callback: a backup agent has failed to come up, or has unexpectedly quit. If the agent failed 3891 * to come up in the first place, the agentBinder argument will be {@code null}. This should 3892 * only be called from the {@link ActivityManager}. 3893 */ agentDisconnected(String packageName)3894 public void agentDisconnected(String packageName) { 3895 // TODO: handle backup being interrupted 3896 synchronized (mAgentConnectLock) { 3897 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 3898 mConnectedAgent = null; 3899 mConnecting = false; 3900 } else { 3901 Slog.w( 3902 TAG, 3903 addUserIdToLogMessage( 3904 mUserId, 3905 "Non-system process uid=" 3906 + Binder.getCallingUid() 3907 + " claiming agent disconnected")); 3908 } 3909 mAgentConnectLock.notifyAll(); 3910 } 3911 } 3912 3913 /** 3914 * An application being installed will need a restore pass, then the {@link PackageManager} will 3915 * need to be told when the restore is finished. 3916 */ restoreAtInstall(String packageName, int token)3917 public void restoreAtInstall(String packageName, int token) { 3918 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 3919 Slog.w( 3920 TAG, 3921 addUserIdToLogMessage( 3922 mUserId, 3923 "Non-system process uid=" 3924 + Binder.getCallingUid() 3925 + " attemping install-time restore")); 3926 return; 3927 } 3928 3929 boolean skip = false; 3930 3931 long restoreSet = getAvailableRestoreToken(packageName); 3932 if (DEBUG) { 3933 Slog.v( 3934 TAG, 3935 addUserIdToLogMessage( 3936 mUserId, 3937 "restoreAtInstall pkg=" 3938 + packageName 3939 + " token=" 3940 + Integer.toHexString(token) 3941 + " restoreSet=" 3942 + Long.toHexString(restoreSet))); 3943 } 3944 if (restoreSet == 0) { 3945 if (MORE_DEBUG) Slog.i(TAG, addUserIdToLogMessage(mUserId, "No restore set")); 3946 skip = true; 3947 } 3948 3949 TransportClient transportClient = 3950 mTransportManager.getCurrentTransportClient("BMS.restoreAtInstall()"); 3951 if (transportClient == null) { 3952 if (DEBUG) Slog.w(TAG, addUserIdToLogMessage(mUserId, "No transport client")); 3953 skip = true; 3954 } 3955 3956 if (!mAutoRestore) { 3957 if (DEBUG) { 3958 Slog.w( 3959 TAG, 3960 addUserIdToLogMessage( 3961 mUserId, "Non-restorable state: auto=" + mAutoRestore)); 3962 } 3963 skip = true; 3964 } 3965 3966 if (!skip) { 3967 try { 3968 // okay, we're going to attempt a restore of this package from this restore set. 3969 // The eventual message back into the Package Manager to run the post-install 3970 // steps for 'token' will be issued from the restore handling code. 3971 3972 mWakelock.acquire(); 3973 3974 OnTaskFinishedListener listener = caller -> { 3975 mTransportManager.disposeOfTransportClient(transportClient, caller); 3976 mWakelock.release(); 3977 }; 3978 3979 if (MORE_DEBUG) { 3980 Slog.d( 3981 TAG, 3982 addUserIdToLogMessage(mUserId, "Restore at install of " + packageName)); 3983 } 3984 Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); 3985 msg.obj = 3986 RestoreParams.createForRestoreAtInstall( 3987 transportClient, 3988 /* observer */ null, 3989 /* monitor */ null, 3990 restoreSet, 3991 packageName, 3992 token, 3993 listener, 3994 getEligibilityRulesForRestoreAtInstall(restoreSet)); 3995 mBackupHandler.sendMessage(msg); 3996 } catch (Exception e) { 3997 // Calling into the transport broke; back off and proceed with the installation. 3998 Slog.e( 3999 TAG, 4000 addUserIdToLogMessage( 4001 mUserId, "Unable to contact transport: " + e.getMessage())); 4002 skip = true; 4003 } 4004 } 4005 4006 if (skip) { 4007 // Auto-restore disabled or no way to attempt a restore 4008 4009 if (transportClient != null) { 4010 mTransportManager.disposeOfTransportClient( 4011 transportClient, "BMS.restoreAtInstall()"); 4012 } 4013 4014 // Tell the PackageManager to proceed with the post-install handling for this package. 4015 if (DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, "Finishing install immediately")); 4016 try { 4017 mPackageManagerBinder.finishPackageInstall(token, false); 4018 } catch (RemoteException e) { /* can't happen */ } 4019 } 4020 } 4021 4022 /** Hand off a restore session. */ beginRestoreSession(String packageName, String transport)4023 public IRestoreSession beginRestoreSession(String packageName, String transport) { 4024 if (DEBUG) { 4025 Slog.v( 4026 TAG, 4027 addUserIdToLogMessage( 4028 mUserId, 4029 "beginRestoreSession: pkg=" + packageName + " transport=" + transport)); 4030 } 4031 4032 boolean needPermission = true; 4033 if (transport == null) { 4034 transport = mTransportManager.getCurrentTransportName(); 4035 4036 if (packageName != null) { 4037 PackageInfo app = null; 4038 try { 4039 app = mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId); 4040 } catch (NameNotFoundException nnf) { 4041 Slog.w( 4042 TAG, 4043 addUserIdToLogMessage( 4044 mUserId, "Asked to restore nonexistent pkg " + packageName)); 4045 throw new IllegalArgumentException("Package " + packageName + " not found"); 4046 } 4047 4048 if (app.applicationInfo.uid == Binder.getCallingUid()) { 4049 // So: using the current active transport, and the caller has asked 4050 // that its own package will be restored. In this narrow use case 4051 // we do not require the caller to hold the permission. 4052 needPermission = false; 4053 } 4054 } 4055 } 4056 4057 if (needPermission) { 4058 mContext.enforceCallingOrSelfPermission( 4059 android.Manifest.permission.BACKUP, "beginRestoreSession"); 4060 } else { 4061 if (DEBUG) { 4062 Slog.d( 4063 TAG, 4064 addUserIdToLogMessage( 4065 mUserId, 4066 "restoring self on current transport; no permission needed")); 4067 } 4068 } 4069 4070 int operationType; 4071 try { 4072 operationType = getOperationTypeFromTransport( 4073 mTransportManager.getTransportClientOrThrow(transport, /* caller */ 4074 "BMS.beginRestoreSession")); 4075 } catch (TransportNotAvailableException | TransportNotRegisteredException 4076 | RemoteException e) { 4077 Slog.w(TAG, "Failed to get operation type from transport: " + e); 4078 return null; 4079 } 4080 4081 synchronized (this) { 4082 if (mActiveRestoreSession != null) { 4083 Slog.i( 4084 TAG, 4085 addUserIdToLogMessage( 4086 mUserId, "Restore session requested but one already active")); 4087 return null; 4088 } 4089 if (mBackupRunning) { 4090 Slog.i( 4091 TAG, 4092 addUserIdToLogMessage( 4093 mUserId, 4094 "Restore session requested but currently running backups")); 4095 return null; 4096 } 4097 mActiveRestoreSession = new ActiveRestoreSession(this, packageName, transport, 4098 getEligibilityRulesForOperation(operationType)); 4099 mBackupHandler.sendEmptyMessageDelayed(MSG_RESTORE_SESSION_TIMEOUT, 4100 mAgentTimeoutParameters.getRestoreSessionTimeoutMillis()); 4101 } 4102 return mActiveRestoreSession; 4103 } 4104 4105 /** Clear the specified restore session. */ clearRestoreSession(ActiveRestoreSession currentSession)4106 public void clearRestoreSession(ActiveRestoreSession currentSession) { 4107 synchronized (this) { 4108 if (currentSession != mActiveRestoreSession) { 4109 Slog.e(TAG, addUserIdToLogMessage(mUserId, "ending non-current restore session")); 4110 } else { 4111 if (DEBUG) { 4112 Slog.v( 4113 TAG, 4114 addUserIdToLogMessage( 4115 mUserId, "Clearing restore session and halting timeout")); 4116 } 4117 mActiveRestoreSession = null; 4118 mBackupHandler.removeMessages(MSG_RESTORE_SESSION_TIMEOUT); 4119 } 4120 } 4121 } 4122 4123 /** 4124 * Note that a currently-active backup agent has notified us that it has completed the given 4125 * outstanding asynchronous backup/restore operation. 4126 */ opComplete(int token, long result)4127 public void opComplete(int token, long result) { 4128 if (MORE_DEBUG) { 4129 Slog.v( 4130 TAG, 4131 addUserIdToLogMessage( 4132 mUserId, 4133 "opComplete: " + Integer.toHexString(token) + " result=" + result)); 4134 } 4135 Operation op = null; 4136 synchronized (mCurrentOpLock) { 4137 op = mCurrentOperations.get(token); 4138 if (op != null) { 4139 if (op.state == OP_TIMEOUT) { 4140 // The operation already timed out, and this is a late response. Tidy up 4141 // and ignore it; we've already dealt with the timeout. 4142 op = null; 4143 mCurrentOperations.delete(token); 4144 } else if (op.state == OP_ACKNOWLEDGED) { 4145 if (DEBUG) { 4146 Slog.w( 4147 TAG, 4148 addUserIdToLogMessage( 4149 mUserId, 4150 "Received duplicate ack for token=" 4151 + Integer.toHexString(token))); 4152 } 4153 op = null; 4154 mCurrentOperations.remove(token); 4155 } else if (op.state == OP_PENDING) { 4156 // Can't delete op from mCurrentOperations. waitUntilOperationComplete can be 4157 // called after we we receive this call. 4158 op.state = OP_ACKNOWLEDGED; 4159 } 4160 } 4161 mCurrentOpLock.notifyAll(); 4162 } 4163 4164 // The completion callback, if any, is invoked on the handler 4165 if (op != null && op.callback != null) { 4166 Pair<BackupRestoreTask, Long> callbackAndResult = Pair.create(op.callback, result); 4167 Message msg = mBackupHandler.obtainMessage(MSG_OP_COMPLETE, callbackAndResult); 4168 mBackupHandler.sendMessage(msg); 4169 } 4170 } 4171 4172 /** Checks if the package is eligible for backup. */ isAppEligibleForBackup(String packageName)4173 public boolean isAppEligibleForBackup(String packageName) { 4174 mContext.enforceCallingOrSelfPermission( 4175 android.Manifest.permission.BACKUP, "isAppEligibleForBackup"); 4176 4177 final long oldToken = Binder.clearCallingIdentity(); 4178 try { 4179 String callerLogString = "BMS.isAppEligibleForBackup"; 4180 TransportClient transportClient = 4181 mTransportManager.getCurrentTransportClient(callerLogString); 4182 boolean eligible = 4183 mScheduledBackupEligibility.appIsRunningAndEligibleForBackupWithTransport( 4184 transportClient, packageName); 4185 if (transportClient != null) { 4186 mTransportManager.disposeOfTransportClient(transportClient, callerLogString); 4187 } 4188 return eligible; 4189 } finally { 4190 Binder.restoreCallingIdentity(oldToken); 4191 } 4192 } 4193 4194 /** Returns the inputted packages that are eligible for backup. */ filterAppsEligibleForBackup(String[] packages)4195 public String[] filterAppsEligibleForBackup(String[] packages) { 4196 mContext.enforceCallingOrSelfPermission( 4197 android.Manifest.permission.BACKUP, "filterAppsEligibleForBackup"); 4198 4199 final long oldToken = Binder.clearCallingIdentity(); 4200 try { 4201 String callerLogString = "BMS.filterAppsEligibleForBackup"; 4202 TransportClient transportClient = 4203 mTransportManager.getCurrentTransportClient(callerLogString); 4204 List<String> eligibleApps = new LinkedList<>(); 4205 for (String packageName : packages) { 4206 if (mScheduledBackupEligibility.appIsRunningAndEligibleForBackupWithTransport( 4207 transportClient, packageName)) { 4208 eligibleApps.add(packageName); 4209 } 4210 } 4211 if (transportClient != null) { 4212 mTransportManager.disposeOfTransportClient(transportClient, callerLogString); 4213 } 4214 return eligibleApps.toArray(new String[eligibleApps.size()]); 4215 } finally { 4216 Binder.restoreCallingIdentity(oldToken); 4217 } 4218 } 4219 getEligibilityRulesForOperation( @perationType int operationType)4220 public BackupEligibilityRules getEligibilityRulesForOperation( 4221 @OperationType int operationType) { 4222 return getEligibilityRules(mPackageManager, mUserId, operationType); 4223 } 4224 getEligibilityRules(PackageManager packageManager, int userId, @OperationType int operationType)4225 private static BackupEligibilityRules getEligibilityRules(PackageManager packageManager, 4226 int userId, @OperationType int operationType) { 4227 return new BackupEligibilityRules(packageManager, 4228 LocalServices.getService(PackageManagerInternal.class), userId, operationType); 4229 } 4230 4231 /** Prints service state for 'dumpsys backup'. */ dump(FileDescriptor fd, PrintWriter pw, String[] args)4232 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4233 final long identityToken = Binder.clearCallingIdentity(); 4234 try { 4235 if (args != null) { 4236 for (String arg : args) { 4237 if ("agents".startsWith(arg)) { 4238 dumpAgents(pw); 4239 return; 4240 } else if ("transportclients".equals(arg.toLowerCase())) { 4241 mTransportManager.dumpTransportClients(pw); 4242 return; 4243 } else if ("transportstats".equals(arg.toLowerCase())) { 4244 mTransportManager.dumpTransportStats(pw); 4245 return; 4246 } 4247 } 4248 } 4249 dumpInternal(pw); 4250 } finally { 4251 Binder.restoreCallingIdentity(identityToken); 4252 } 4253 } 4254 dumpAgents(PrintWriter pw)4255 private void dumpAgents(PrintWriter pw) { 4256 List<PackageInfo> agentPackages = allAgentPackages(); 4257 pw.println("Defined backup agents:"); 4258 for (PackageInfo pkg : agentPackages) { 4259 pw.print(" "); 4260 pw.print(pkg.packageName); 4261 pw.println(':'); 4262 pw.print(" "); 4263 pw.println(pkg.applicationInfo.backupAgentName); 4264 } 4265 } 4266 dumpInternal(PrintWriter pw)4267 private void dumpInternal(PrintWriter pw) { 4268 // Add prefix for only non-system users so that system user dumpsys is the same as before 4269 String userPrefix = mUserId == UserHandle.USER_SYSTEM ? "" : "User " + mUserId + ":"; 4270 synchronized (mQueueLock) { 4271 pw.println(userPrefix + "Backup Manager is " + (mEnabled ? "enabled" : "disabled") 4272 + " / " + (!mSetupComplete ? "not " : "") + "setup complete / " 4273 + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init"); 4274 pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled")); 4275 if (mBackupRunning) pw.println("Backup currently running"); 4276 pw.println(isBackupOperationInProgress() ? "Backup in progress" : "No backups running"); 4277 pw.println("Last backup pass started: " + mLastBackupPass 4278 + " (now = " + System.currentTimeMillis() + ')'); 4279 pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled(mUserId)); 4280 4281 pw.println(userPrefix + "Transport whitelist:"); 4282 for (ComponentName transport : mTransportManager.getTransportWhitelist()) { 4283 pw.print(" "); 4284 pw.println(transport.flattenToShortString()); 4285 } 4286 4287 pw.println(userPrefix + "Available transports:"); 4288 final String[] transports = listAllTransports(); 4289 if (transports != null) { 4290 for (String t : transports) { 4291 pw.println((t.equals(mTransportManager.getCurrentTransportName()) ? " * " 4292 : " ") + t); 4293 try { 4294 File dir = new File(mBaseStateDir, 4295 mTransportManager.getTransportDirName(t)); 4296 pw.println(" destination: " 4297 + mTransportManager.getTransportCurrentDestinationString(t)); 4298 pw.println(" intent: " 4299 + mTransportManager.getTransportConfigurationIntent(t)); 4300 for (File f : dir.listFiles()) { 4301 pw.println( 4302 " " + f.getName() + " - " + f.length() + " state bytes"); 4303 } 4304 } catch (Exception e) { 4305 Slog.e(TAG, addUserIdToLogMessage(mUserId, "Error in transport"), e); 4306 pw.println(" Error: " + e); 4307 } 4308 } 4309 } 4310 4311 mTransportManager.dumpTransportClients(pw); 4312 4313 pw.println(userPrefix + "Pending init: " + mPendingInits.size()); 4314 for (String s : mPendingInits) { 4315 pw.println(" " + s); 4316 } 4317 4318 pw.print(userPrefix + "Ancestral: "); 4319 pw.println(Long.toHexString(mAncestralToken)); 4320 pw.print(userPrefix + "Current: "); 4321 pw.println(Long.toHexString(mCurrentToken)); 4322 4323 int numPackages = mBackupParticipants.size(); 4324 pw.println(userPrefix + "Participants:"); 4325 for (int i = 0; i < numPackages; i++) { 4326 int uid = mBackupParticipants.keyAt(i); 4327 pw.print(" uid: "); 4328 pw.println(uid); 4329 HashSet<String> participants = mBackupParticipants.valueAt(i); 4330 for (String app : participants) { 4331 pw.println(" " + app); 4332 } 4333 } 4334 4335 pw.println(userPrefix + "Ancestral packages: " 4336 + (mAncestralPackages == null ? "none" : mAncestralPackages.size())); 4337 if (mAncestralPackages != null) { 4338 for (String pkg : mAncestralPackages) { 4339 pw.println(" " + pkg); 4340 } 4341 } 4342 4343 Set<String> processedPackages = mProcessedPackagesJournal.getPackagesCopy(); 4344 pw.println(userPrefix + "Ever backed up: " + processedPackages.size()); 4345 for (String pkg : processedPackages) { 4346 pw.println(" " + pkg); 4347 } 4348 4349 pw.println(userPrefix + "Pending key/value backup: " + mPendingBackups.size()); 4350 for (BackupRequest req : mPendingBackups.values()) { 4351 pw.println(" " + req); 4352 } 4353 4354 pw.println(userPrefix + "Full backup queue:" + mFullBackupQueue.size()); 4355 for (FullBackupEntry entry : mFullBackupQueue) { 4356 pw.print(" "); 4357 pw.print(entry.lastBackup); 4358 pw.print(" : "); 4359 pw.println(entry.packageName); 4360 } 4361 } 4362 } 4363 4364 @VisibleForTesting getOperationTypeFromTransport(TransportClient transportClient)4365 @OperationType int getOperationTypeFromTransport(TransportClient transportClient) 4366 throws TransportNotAvailableException, RemoteException { 4367 if (!shouldUseNewBackupEligibilityRules()) { 4368 // Return the default to stick to the legacy behaviour. 4369 return OperationType.BACKUP; 4370 } 4371 4372 long oldCallingId = Binder.clearCallingIdentity(); 4373 try { 4374 IBackupTransport transport = transportClient.connectOrThrow( 4375 /* caller */ "BMS.getOperationTypeFromTransport"); 4376 if ((transport.getTransportFlags() & BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) { 4377 return OperationType.MIGRATION; 4378 } else { 4379 return OperationType.BACKUP; 4380 } 4381 } finally { 4382 Binder.restoreCallingIdentity(oldCallingId); 4383 } 4384 } 4385 4386 @VisibleForTesting shouldUseNewBackupEligibilityRules()4387 boolean shouldUseNewBackupEligibilityRules() { 4388 return FeatureFlagUtils.isEnabled(mContext, 4389 FeatureFlagUtils.SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES); 4390 } 4391 addUserIdToLogMessage(int userId, String message)4392 private static String addUserIdToLogMessage(int userId, String message) { 4393 return "[UserID:" + userId + "] " + message; 4394 } 4395 4396 getBackupManagerBinder()4397 public IBackupManager getBackupManagerBinder() { 4398 return mBackupManagerBinder; 4399 } 4400 } 4401