Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8056728f authored by Oscar Key's avatar Oscar Key
Browse files

Move backup of @pm@ into its own state.

Previously it shared the INITIAL state with various set up work and
initializing the transport if needed. By moving it to its own state this
will mean we can retry a non-incremental backup of @pm@ if the transport
indicates that it has lost the state.

I removed the "mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED" as
the mStatus could never have this value at that point.
TRANSPORT_NOT_INITIALIZED is returned by the transport.performBackup(),
which is not executed until after beginBackup() has returned.

Bug: 71887023
Test: Manually tested init case, incremental case, @pm@ error case, init
error case. There are no unit tests for this file, and it's 1200 lines
long which makes writing them for IC difficult.

Change-Id: I23b7512391068316f4c1039faf88cc27905f4492
parent a8c77948
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ package com.android.server.backup.internal;
 */
enum BackupState {
    INITIAL,
    BACKUP_PM,
    RUNNING_QUEUE,
    FINAL
}
+56 −29
Original line number Diff line number Diff line
@@ -224,6 +224,10 @@ public class PerformBackupTask implements BackupRestoreTask {
                    beginBackup();
                    break;

                case BACKUP_PM:
                    backupPm();
                    break;

                case RUNNING_QUEUE:
                    invokeNextAgent();
                    break;
@@ -239,8 +243,7 @@ public class PerformBackupTask implements BackupRestoreTask {
        }
    }

    // We're starting a backup pass.  Initialize the transport and send
    // the PM metadata blob if we haven't already.
    // We're starting a backup pass.  Initialize the transport if we haven't already.
    private void beginBackup() {
        if (DEBUG_BACKUP_TRACE) {
            backupManagerService.clearBackupTrace();
@@ -320,53 +323,77 @@ public class PerformBackupTask implements BackupRestoreTask {
                Slog.d(TAG, "Skipping backup of package metadata.");
                executeNextState(BackupState.RUNNING_QUEUE);
            } else {
                // The package manager doesn't have a proper <application> etc, but since
                // it's running here in the system process we can just set up its agent
                // directly and use a synthetic BackupRequest.  We always run this pass
                // because it's cheap and this way we guarantee that we don't get out of
                // step even if we're selecting among various transports at run time.
                // As the package manager is running here in the system process we can just set up
                // its agent directly. Thus we always run this pass because it's cheap and this way
                // we guarantee that we don't get out of step even if we're selecting among various
                // transports at run time.
                if (mStatus == BackupTransport.TRANSPORT_OK) {
                    executeNextState(BackupState.BACKUP_PM);
                }
            }
        } catch (Exception e) {
            Slog.e(TAG, "Error in backup thread during init", e);
            backupManagerService.addBackupTrace("Exception in backup thread during init: " + e);
            mStatus = BackupTransport.TRANSPORT_ERROR;
        } finally {
            // If we've succeeded so far, we will move to the BACKUP_PM state. If something has gone
            // wrong then that won't have happen so cleanup.
            backupManagerService.addBackupTrace("exiting prelim: " + mStatus);
            if (mStatus != BackupTransport.TRANSPORT_OK) {
                // if things went wrong at this point, we need to
                // restage everything and try again later.
                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
                // In case of any other error, it's backup transport error.
                BackupObserverUtils.sendBackupFinished(mObserver,
                        BackupManager.ERROR_TRANSPORT_ABORTED);
                executeNextState(BackupState.FINAL);
            }
        }
    }

    private void backupPm() {
        try {
            // The package manager doesn't have a proper <application> etc, but since it's running
            // here in the system process we can just set up its agent directly and use a synthetic
            // BackupRequest.
            PackageManagerBackupAgent pmAgent = backupManagerService.makeMetadataAgent();
            mStatus = invokeAgentForBackup(
                    PACKAGE_MANAGER_SENTINEL,
                    IBackupAgent.Stub.asInterface(pmAgent.onBind()));
            backupManagerService.addBackupTrace("PMBA invoke: " + mStatus);

                    // Because the PMBA is a local instance, it has already executed its
                    // backup callback and returned.  Blow away the lingering (spurious)
                    // pending timeout message for it.
            // Because the PMBA is a local instance, it has already executed its backup callback and
            // returned.  Blow away the lingering (spurious) pending timeout message for it.
            backupManagerService.getBackupHandler().removeMessages(
                    MSG_BACKUP_OPERATION_TIMEOUT);
                }
            }

            if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
                // The backend reports that our dataset has been wiped.  Note this in
                // the event log; the no-success code below will reset the backup
                // state as well.
                EventLog.writeEvent(EventLogTags.BACKUP_RESET, transportName);
            }
        } catch (Exception e) {
            Slog.e(TAG, "Error in backup thread", e);
            backupManagerService.addBackupTrace("Exception in backup thread: " + e);
            Slog.e(TAG, "Error in backup thread during pm", e);
            backupManagerService.addBackupTrace("Exception in backup thread during pm: " + e);
            mStatus = BackupTransport.TRANSPORT_ERROR;
        } finally {
            // If we've succeeded so far, invokeAgentForBackup() will have run the PM
            // metadata and its completion/timeout callback will continue the state
            // machine chain.  If it failed that won't happen; we handle that now.
            backupManagerService.addBackupTrace("exiting prelim: " + mStatus);
            backupManagerService.addBackupTrace("exiting backupPm: " + mStatus);
            if (mStatus != BackupTransport.TRANSPORT_OK) {
                // if things went wrong at this point, we need to
                // restage everything and try again later.
                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
                // In case of any other error, it's backup transport error.
                BackupObserverUtils.sendBackupFinished(mObserver,
                        BackupManager.ERROR_TRANSPORT_ABORTED);
                        invokeAgentToObserverError(mStatus));
                executeNextState(BackupState.FINAL);
            }
        }
    }

    private int invokeAgentToObserverError(int error) {
        if (error == BackupTransport.AGENT_ERROR) {
            return BackupManager.ERROR_AGENT_FAILURE;
        } else {
            return BackupManager.ERROR_TRANSPORT_ABORTED;
        }
    }

    // Transport has been initialized and the PM metadata submitted successfully
    // if that was warranted.  Now we process the single next thing in the queue.
    private void invokeNextAgent() {