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