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