From b89e1405cf9f1da533dc0843390a1b6783abb0f4 Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Tue, 6 Jan 2015 15:48:33 -0800 Subject: [PATCH] Support single-package backup rejection by the transport We now cleanly handle the case of the transport blacklisting specific packages from key/value backup. Previously we would halt the entire backup pass and reschedule if the transport returned any error from performBackup(pkg). Now, we recognize the TRANSPORT_PACKAGE_REJECTED result from that invocation, and properly drop that package's work but proceed with running the rest of the backup queue as expected. Bug 18694053 Change-Id: Id0dd6d59492bdea9f970540d776f37db0cc5d99c --- core/java/android/app/backup/BackupTransport.java | 7 ++++-- .../server/backup/BackupManagerService.java | 29 +++++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java index 70bb5e4f64a7..e853540e5d50 100644 --- a/core/java/android/app/backup/BackupTransport.java +++ b/core/java/android/app/backup/BackupTransport.java @@ -213,8 +213,9 @@ public class BackupTransport { /** * Send one application's key/value data update to the backup destination. The - * transport may send the data immediately, or may buffer it. After this is called, - * {@link #finishBackup} will be called to ensure the data is sent and recorded successfully. + * transport may send the data immediately, or may buffer it. If this method returns + * {@link #TRANSPORT_OK}, {@link #finishBackup} will then be called to ensure the data + * is sent and recorded successfully. * * @param packageInfo The identity of the application whose data is being backed up. * This specifically includes the signature list for the package. @@ -226,6 +227,8 @@ public class BackupTransport { * is to provide a guarantee that no stale data exists in the restore set when the * device begins providing incremental backups. * @return one of {@link BackupTransport#TRANSPORT_OK} (OK so far), + * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED} (to suppress backup of this + * specific package, but allow others to proceed), * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure), or * {@link BackupTransport#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has * become lost due to inactivity purge or some other reason and needs re-initializing) diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 8c74ca5a93ff..7d085a33f00b 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -2786,21 +2786,30 @@ public class BackupManagerService { addBackupTrace("finishing op on transport"); mStatus = mTransport.finishBackup(); addBackupTrace("finished: " + mStatus); + } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) { + addBackupTrace("transport rejected package"); } } else { if (DEBUG) Slog.i(TAG, "no backup data written; not calling transport"); addBackupTrace("no data to send"); } - // After successful transport, delete the now-stale data - // and juggle the files so that next time we supply the agent - // with the new state file it just created. if (mStatus == BackupTransport.TRANSPORT_OK) { + // After successful transport, delete the now-stale data + // and juggle the files so that next time we supply the agent + // with the new state file it just created. mBackupDataName.delete(); mNewStateName.renameTo(mSavedStateName); EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size); logBackupComplete(pkgName); + } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) { + // The transport has rejected backup of this specific package. Roll it + // back but proceed with running the rest of the queue. + mBackupDataName.delete(); + mNewStateName.delete(); + EventLogTags.writeBackupAgentFailure(pkgName, "Transport rejected"); } else { + // Actual transport-level failure to communicate the data to the backend EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName); } } catch (Exception e) { @@ -2811,15 +2820,17 @@ public class BackupManagerService { try { if (backupData != null) backupData.close(); } catch (IOException e) {} } - // If we encountered an error here it's a transport-level failure. That - // means we need to halt everything and reschedule everything for next time. final BackupState nextState; - if (mStatus != BackupTransport.TRANSPORT_OK) { + if (mStatus == BackupTransport.TRANSPORT_OK + || mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) { + // Success or single-package rejection. Proceed with the next app if any, + // otherwise we're done. + nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE; + } else { + // Any other error here indicates a transport-level failure. That means + // we need to halt everything and reschedule everything for next time. revertAndEndBackup(); nextState = BackupState.FINAL; - } else { - // Success! Proceed with the next app if any, otherwise we're done. - nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE; } executeNextState(nextState); -- 2.11.0