diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java index dd29a04e5f543..2788218d8a4b3 100644 --- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java @@ -2158,8 +2158,17 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter mFullBackupQueue.remove(0); CountDownLatch latch = new CountDownLatch(1); String[] pkg = new String[]{entry.packageName}; - mRunningFullBackupTask = new PerformFullTransportBackupTask(this, null, pkg, true, - scheduledJob, latch, null, null, false /* userInitiated */); + mRunningFullBackupTask = PerformFullTransportBackupTask.newWithCurrentTransport( + this, + /* observer */ null, + pkg, + /* updateSchedule */ true, + scheduledJob, + latch, + /* backupObserver */ null, + /* monitor */ null, + /* userInitiated */ false, + "BMS.beginFullBackup()"); // Acquiring wakelock for PerformFullTransportBackupTask before its start. mWakelock.acquire(); (new Thread(mRunningFullBackupTask)).start(); @@ -2513,8 +2522,17 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter final long oldId = Binder.clearCallingIdentity(); try { CountDownLatch latch = new CountDownLatch(1); - PerformFullTransportBackupTask task = new PerformFullTransportBackupTask(this, null, - pkgNames, false, null, latch, null, null, false /* userInitiated */); + Runnable task = PerformFullTransportBackupTask.newWithCurrentTransport( + this, + /* observer */ null, + pkgNames, + /* updateSchedule */ false, + /* runningJob */ null, + latch, + /* backupObserver */ null, + /* monitor */ null, + /* userInitiated */ false, + "BMS.fullTransportBackup()"); // Acquiring wakelock for PerformFullTransportBackupTask before its start. mWakelock.acquire(); (new Thread(task, "full-transport-master")).start(); diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java index 90134e1a3eada..d5b3d98f98970 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java +++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java @@ -24,6 +24,7 @@ import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_B import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT; import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL; +import android.annotation.Nullable; import android.app.IBackupAgent; import android.app.backup.BackupManager; import android.app.backup.BackupManagerMonitor; @@ -46,7 +47,11 @@ import com.android.server.EventLogTags; import com.android.server.backup.BackupRestoreTask; import com.android.server.backup.FullBackupJob; import com.android.server.backup.RefactoredBackupManagerService; +import com.android.server.backup.TransportManager; +import com.android.server.backup.internal.OnTaskFinishedListener; import com.android.server.backup.internal.Operation; +import com.android.server.backup.transport.TransportClient; +import com.android.server.backup.transport.TransportNotAvailableException; import com.android.server.backup.utils.AppBackupUtils; import com.android.server.backup.utils.BackupManagerMonitorUtils; import com.android.server.backup.utils.BackupObserverUtils; @@ -89,6 +94,36 @@ import java.util.concurrent.atomic.AtomicLong; * mBackupRunner.getBackupResultBlocking(). */ public class PerformFullTransportBackupTask extends FullBackupTask implements BackupRestoreTask { + public static PerformFullTransportBackupTask newWithCurrentTransport( + RefactoredBackupManagerService backupManagerService, + IFullBackupRestoreObserver observer, + String[] whichPackages, + boolean updateSchedule, + FullBackupJob runningJob, + CountDownLatch latch, + IBackupObserver backupObserver, + IBackupManagerMonitor monitor, + boolean userInitiated, + String caller) { + TransportManager transportManager = backupManagerService.getTransportManager(); + TransportClient transportClient = transportManager.getCurrentTransportClient(caller); + OnTaskFinishedListener listener = + listenerCaller -> + transportManager.disposeOfTransportClient(transportClient, listenerCaller); + return new PerformFullTransportBackupTask( + backupManagerService, + transportClient, + observer, + whichPackages, + updateSchedule, + runningJob, + latch, + backupObserver, + monitor, + listener, + userInitiated); + } + private static final String TAG = "PFTBT"; private RefactoredBackupManagerService backupManagerService; @@ -102,9 +137,10 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba IBackupObserver mBackupObserver; IBackupManagerMonitor mMonitor; boolean mUserInitiated; - private volatile IBackupTransport mTransport; SinglePackageBackupRunner mBackupRunner; private final int mBackupRunnerOpToken; + private final OnTaskFinishedListener mListener; + private final TransportClient mTransportClient; // This is true when a backup operation for some package is in progress. private volatile boolean mIsDoingBackup; @@ -112,18 +148,22 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba private final int mCurrentOpToken; public PerformFullTransportBackupTask(RefactoredBackupManagerService backupManagerService, + TransportClient transportClient, IFullBackupRestoreObserver observer, String[] whichPackages, boolean updateSchedule, FullBackupJob runningJob, CountDownLatch latch, IBackupObserver backupObserver, - IBackupManagerMonitor monitor, boolean userInitiated) { + IBackupManagerMonitor monitor, @Nullable OnTaskFinishedListener listener, + boolean userInitiated) { super(observer); this.backupManagerService = backupManagerService; + mTransportClient = transportClient; mUpdateSchedule = updateSchedule; mLatch = latch; mJob = runningJob; mPackages = new ArrayList<>(whichPackages.length); mBackupObserver = backupObserver; mMonitor = monitor; + mListener = (listener != null) ? listener : OnTaskFinishedListener.NOP; mUserInitiated = userInitiated; mCurrentOpToken = backupManagerService.generateRandomIntegerToken(); mBackupRunnerOpToken = backupManagerService.generateRandomIntegerToken(); @@ -241,8 +281,11 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba if (mIsDoingBackup) { backupManagerService.handleCancel(mBackupRunnerOpToken, cancelAll); try { - mTransport.cancelFullBackup(); - } catch (RemoteException e) { + // If we're running a backup we should be connected to a transport + IBackupTransport transport = + mTransportClient.getConnectedTransport("PFTBT.handleCancel()"); + transport.cancelFullBackup(); + } catch (RemoteException | TransportNotAvailableException e) { Slog.w(TAG, "Error calling cancelFullBackup() on transport: " + e); // Can't do much. } @@ -291,8 +334,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba return; } - mTransport = backupManagerService.getTransportManager().getCurrentTransportBinder(); - if (mTransport == null) { + IBackupTransport transport = mTransportClient.connect("PFTBT.run()"); + if (transport == null) { Slog.w(TAG, "Transport not present; full data backup not performed"); backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED; mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor, @@ -325,17 +368,17 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba if (mCancelAll) { break; } - backupPackageStatus = mTransport.performFullBackup(currentPackage, + backupPackageStatus = transport.performFullBackup(currentPackage, transportPipes[0], flags); if (backupPackageStatus == BackupTransport.TRANSPORT_OK) { - quota = mTransport.getBackupQuota(currentPackage.packageName, + quota = transport.getBackupQuota(currentPackage.packageName, true /* isFullBackup */); // Now set up the backup engine / data source end of things enginePipes = ParcelFileDescriptor.createPipe(); mBackupRunner = new SinglePackageBackupRunner(enginePipes[1], currentPackage, - mTransport, quota, mBackupRunnerOpToken); + mTransportClient, quota, mBackupRunnerOpToken); // The runner dup'd the pipe half, so we close it here enginePipes[1].close(); enginePipes[1] = null; @@ -389,7 +432,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba out.write(buffer, 0, nRead); synchronized (mCancelLock) { if (!mCancelAll) { - backupPackageStatus = mTransport.sendBackupData(nRead); + backupPackageStatus = transport.sendBackupData(nRead); } } totalRead += nRead; @@ -425,12 +468,12 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba // result based on what finishBackup() returns. If we're in a // failure case already, preserve that result and ignore whatever // finishBackup() reports. - final int finishResult = mTransport.finishBackup(); + final int finishResult = transport.finishBackup(); if (backupPackageStatus == BackupTransport.TRANSPORT_OK) { backupPackageStatus = finishResult; } } else { - mTransport.cancelFullBackup(); + transport.cancelFullBackup(); } } } @@ -469,7 +512,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba // Also ask the transport how long it wants us to wait before // moving on to the next package, if any. - backoff = mTransport.requestFullBackupTime(); + backoff = transport.requestFullBackupTime(); if (DEBUG_SCHEDULING) { Slog.i(TAG, "Transport suggested backoff=" + backoff); } @@ -591,6 +634,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba backupManagerService.setRunningFullBackupTask(null); } + mListener.onFinished("PFTBT.run()"); + mLatch.countDown(); // Now that we're actually done with schedule-driven work, reschedule @@ -633,12 +678,13 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba class SinglePackageBackupPreflight implements BackupRestoreTask, FullBackupPreflight { final AtomicLong mResult = new AtomicLong(BackupTransport.AGENT_ERROR); final CountDownLatch mLatch = new CountDownLatch(1); - final IBackupTransport mTransport; + final TransportClient mTransportClient; final long mQuota; private final int mCurrentOpToken; - SinglePackageBackupPreflight(IBackupTransport transport, long quota, int currentOpToken) { - mTransport = transport; + SinglePackageBackupPreflight( + TransportClient transportClient, long quota, int currentOpToken) { + mTransportClient = transportClient; mQuota = quota; mCurrentOpToken = currentOpToken; } @@ -672,7 +718,9 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba Slog.v(TAG, "Got preflight response; size=" + totalSize); } - result = mTransport.checkFullBackupSize(totalSize); + IBackupTransport transport = + mTransportClient.connectOrThrow("PFTBT$SPBP.preflightFullBackup()"); + result = transport.checkFullBackupSize(totalSize); if (result == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) { if (MORE_DEBUG) { Slog.d(TAG, "Package hit quota limit on preflight " + @@ -739,12 +787,13 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba private volatile boolean mIsCancelled; SinglePackageBackupRunner(ParcelFileDescriptor output, PackageInfo target, - IBackupTransport transport, long quota, int currentOpToken) throws IOException { + TransportClient transportClient, long quota, int currentOpToken) + throws IOException { mOutput = ParcelFileDescriptor.dup(output.getFileDescriptor()); mTarget = target; mCurrentOpToken = currentOpToken; mEphemeralToken = backupManagerService.generateRandomIntegerToken(); - mPreflight = new SinglePackageBackupPreflight(transport, quota, mEphemeralToken); + mPreflight = new SinglePackageBackupPreflight(transportClient, quota, mEphemeralToken); mPreflightLatch = new CountDownLatch(1); mBackupLatch = new CountDownLatch(1); mPreflightResult = BackupTransport.AGENT_ERROR; diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java index 1fa215a1664a8..5be1b3905bbc2 100644 --- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java +++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java @@ -184,11 +184,11 @@ public class PerformBackupTask implements BackupRestoreTask { mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]); mFullBackupTask = new PerformFullTransportBackupTask(backupManagerService, - /*fullBackupRestoreObserver*/ - null, + transportClient, + /*fullBackupRestoreObserver*/ null, fullBackups, /*updateSchedule*/ false, /*runningJob*/ null, latch, - mObserver, mMonitor, mUserInitiated); + mObserver, mMonitor, mListener, mUserInitiated); registerTask(); backupManagerService.addBackupTrace("STATE => INITIAL"); @@ -585,11 +585,11 @@ public class PerformBackupTask implements BackupRestoreTask { if (!mCancelAll && mStatus == BackupTransport.TRANSPORT_OK && mPendingFullBackups != null && !mPendingFullBackups.isEmpty()) { - // TODO(brufino): Move the onFinish() call to the full-backup task - mListener.onFinished(callerLogString); Slog.d(TAG, "Starting full backups for: " + mPendingFullBackups); // Acquiring wakelock for PerformFullTransportBackupTask before its start. backupManagerService.getWakelock().acquire(); + // The full-backup task is now responsible for calling onFinish() on mListener, which + // was the listener we passed it. (new Thread(mFullBackupTask, "full-transport-requested")).start(); } else if (mCancelAll) { mListener.onFinished(callerLogString); diff --git a/services/backup/java/com/android/server/backup/transport/TransportClient.java b/services/backup/java/com/android/server/backup/transport/TransportClient.java index 9c39729f0ddaa..65f950228723f 100644 --- a/services/backup/java/com/android/server/backup/transport/TransportClient.java +++ b/services/backup/java/com/android/server/backup/transport/TransportClient.java @@ -367,6 +367,25 @@ public class TransportClient { return transport; } + /** + * If the {@link TransportClient} is already connected to the transport, returns the transport, + * otherwise throws {@link TransportNotAvailableException}. + * + * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check + * {@link #connectAsync(TransportConnectionListener, String)} for more details. + * @return A {@link IBackupTransport} transport binder instance. + * @throws TransportNotAvailableException if not connected. + */ + public IBackupTransport getConnectedTransport(String caller) + throws TransportNotAvailableException { + IBackupTransport transport = mTransport; + if (transport == null) { + log(Log.ERROR, caller, "Transport not connected"); + throw new TransportNotAvailableException(); + } + return transport; + } + @Override public String toString() { return "TransportClient{" diff --git a/services/backup/java/com/android/server/backup/transport/TransportNotAvailableException.java b/services/backup/java/com/android/server/backup/transport/TransportNotAvailableException.java index a02f03c2d1cbe..c4e5a1dd74307 100644 --- a/services/backup/java/com/android/server/backup/transport/TransportNotAvailableException.java +++ b/services/backup/java/com/android/server/backup/transport/TransportNotAvailableException.java @@ -25,7 +25,7 @@ import com.android.internal.backup.IBackupTransport; * * @see TransportClient#connectAsync(TransportConnectionListener, String) */ -class TransportNotAvailableException extends Exception { +public class TransportNotAvailableException extends Exception { TransportNotAvailableException() { super("Transport not available"); } diff --git a/services/backup/java/com/android/server/backup/transport/TransportUtils.java b/services/backup/java/com/android/server/backup/transport/TransportUtils.java index 514717f46b9f0..85599b7825620 100644 --- a/services/backup/java/com/android/server/backup/transport/TransportUtils.java +++ b/services/backup/java/com/android/server/backup/transport/TransportUtils.java @@ -25,6 +25,7 @@ import com.android.internal.backup.IBackupTransport; /** Utility methods for transport-related operations. */ public class TransportUtils { + private static final String TAG = "TransportUtils"; /** * Throws {@link TransportNotAvailableException} if {@param transport} is null. The semantics is @@ -33,6 +34,7 @@ public class TransportUtils { public static IBackupTransport checkTransport(@Nullable IBackupTransport transport) throws TransportNotAvailableException { if (transport == null) { + log(Log.ERROR, TAG, "Transport not available"); throw new TransportNotAvailableException(); } return transport;