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