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