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

Commit 5148582e authored by Anton Philippov's avatar Anton Philippov
Browse files

Use FullRestoreEngine in adb restore.

PerformAdbRestoreTask and FullRestoreEngine has shared a lot of code,
remove the copy that was in PerformAdbRestoreTask.

Test: adb restore
Change-Id: Ib4ce8b50eff8aed4a2c0660808c05b80f378ea98
parent 90950d7e
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
package com.android.server.backup.restore;

import android.app.IBackupAgent;
import android.os.RemoteException;

import com.android.server.backup.BackupManagerService;

/**
 * Runner that can be placed on a separate thread to do in-process invocation of the "restore
 * finished" API asynchronously.  Used by adb restore.
 */
public class AdbRestoreFinishedRunnable implements Runnable {

    private final IBackupAgent mAgent;
    private final int mToken;
    private final BackupManagerService mBackupManagerService;

    AdbRestoreFinishedRunnable(IBackupAgent agent, int token,
            BackupManagerService backupManagerService) {
        mAgent = agent;
        mToken = token;
        mBackupManagerService = backupManagerService;
    }

    @Override
    public void run() {
        try {
            mAgent.doRestoreFinished(mToken, mBackupManagerService.getBackupManagerBinder());
        } catch (RemoteException e) {
            // never happens; this is used only for local binder calls
        }
    }
}
+45 −7
Original line number Diff line number Diff line
@@ -122,15 +122,17 @@ public class FullRestoreEngine extends RestoreEngine {

    // Widget blob to be restored out-of-band
    private byte[] mWidgetData = null;
    private long mAppVersion;

    final int mEphemeralOpToken;

    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
    final boolean mIsAdbRestore;

    public FullRestoreEngine(BackupManagerService backupManagerService,
            BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
            IBackupManagerMonitor monitor, PackageInfo onlyPackage, boolean allowApks,
            boolean allowObbs, int ephemeralOpToken) {
            boolean allowObbs, int ephemeralOpToken, boolean isAdbRestore) {
        mBackupManagerService = backupManagerService;
        mEphemeralOpToken = ephemeralOpToken;
        mMonitorTask = monitorTask;
@@ -144,6 +146,7 @@ public class FullRestoreEngine extends RestoreEngine {
        mAgentTimeoutParameters = Preconditions.checkNotNull(
                backupManagerService.getAgentTimeoutParameters(),
                "Timeout parameters cannot be null");
        mIsAdbRestore = isAdbRestore;
    }

    public IBackupAgent getAgent() {
@@ -209,7 +212,7 @@ public class FullRestoreEngine extends RestoreEngine {
                        }
                        // Now we're really done
                        tearDownPipes();
                        tearDownAgent(mTargetApp);
                        tearDownAgent(mTargetApp, mIsAdbRestore);
                        mTargetApp = null;
                        mAgentPackage = null;
                    }
@@ -218,6 +221,9 @@ public class FullRestoreEngine extends RestoreEngine {
                if (info.path.equals(BACKUP_MANIFEST_FILENAME)) {
                    Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
                            info);
                    // readAppManifestAndReturnSignatures() will have extracted the version from
                    // the manifest, so we save it to use in adb key-value restore later.
                    mAppVersion = info.version;
                    PackageManagerInternal pmi = LocalServices.getService(
                            PackageManagerInternal.class);
                    RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
@@ -362,7 +368,9 @@ public class FullRestoreEngine extends RestoreEngine {
                            // All set; now set up the IPC and launch the agent
                            setUpPipes();
                            mAgent = mBackupManagerService.bindToAgentSynchronous(mTargetApp,
                                    ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL);
                                    FullBackup.KEY_VALUE_DATA_TOKEN.equals(info.domain)
                                            ? ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL
                                            : ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL);
                            mAgentPackage = pkg;
                        } catch (IOException e) {
                            // fall through to error handling
@@ -419,6 +427,8 @@ public class FullRestoreEngine extends RestoreEngine {
                                    Slog.d(TAG, "Restoring key-value file for " + pkg
                                            + " : " + info.path);
                                }
                                // Set the version saved from manifest entry.
                                info.version = mAppVersion;
                                KeyValueAdbRestoreEngine restoreEngine =
                                        new KeyValueAdbRestoreEngine(
                                                mBackupManagerService,
@@ -506,7 +516,7 @@ public class FullRestoreEngine extends RestoreEngine {
                            mBackupManagerService.getBackupHandler().removeMessages(
                                    MSG_RESTORE_OPERATION_TIMEOUT);
                            tearDownPipes();
                            tearDownAgent(mTargetApp);
                            tearDownAgent(mTargetApp, false);
                            mAgent = null;
                            mPackagePolicies.put(pkg, RestorePolicy.IGNORE);

@@ -559,7 +569,7 @@ public class FullRestoreEngine extends RestoreEngine {
            tearDownPipes();
            setRunning(false);
            if (mustKillAgent) {
                tearDownAgent(mTargetApp);
                tearDownAgent(mTargetApp, mIsAdbRestore);
            }
        }
        return (info != null);
@@ -588,9 +598,37 @@ public class FullRestoreEngine extends RestoreEngine {
        }
    }

    private void tearDownAgent(ApplicationInfo app) {
    private void tearDownAgent(ApplicationInfo app, boolean doRestoreFinished) {
        if (mAgent != null) {
            try {
                // In the adb restore case, we do restore-finished here
                if (doRestoreFinished) {
                    final int token = mBackupManagerService.generateRandomIntegerToken();
                    long fullBackupAgentTimeoutMillis =
                            mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
                    final AdbRestoreFinishedLatch latch = new AdbRestoreFinishedLatch(
                            mBackupManagerService, token);
                    mBackupManagerService.prepareOperationTimeout(
                            token, fullBackupAgentTimeoutMillis, latch, OP_TYPE_RESTORE_WAIT);
                    if (mTargetApp.processName.equals("system")) {
                        if (MORE_DEBUG) {
                            Slog.d(TAG, "system agent - restoreFinished on thread");
                        }
                        Runnable runner = new AdbRestoreFinishedRunnable(mAgent, token,
                                mBackupManagerService);
                        new Thread(runner, "restore-sys-finished-runner").start();
                    } else {
                        mAgent.doRestoreFinished(token,
                                mBackupManagerService.getBackupManagerBinder());
                    }

                    latch.await();
                }

                mBackupManagerService.tearDownAgentAndKill(app);
            } catch (RemoteException e) {
                Slog.d(TAG, "Lost app trying to shut down");
            }
            mAgent = null;
        }
    }
+63 −0
Original line number Diff line number Diff line
package com.android.server.backup.restore;

import android.os.ParcelFileDescriptor;

import libcore.io.IoUtils;

import java.io.FileInputStream;
import java.io.InputStream;

class FullRestoreEngineThread implements Runnable {

    FullRestoreEngine mEngine;
    InputStream mEngineStream;
    private final boolean mMustKillAgent;

    FullRestoreEngineThread(FullRestoreEngine engine, ParcelFileDescriptor engineSocket) {
        mEngine = engine;
        engine.setRunning(true);
        // We *do* want this FileInputStream to own the underlying fd, so that
        // when we are finished with it, it closes this end of the pipe in a way
        // that signals its other end.
        mEngineStream = new FileInputStream(engineSocket.getFileDescriptor(), true);
        // Tell it to be sure to leave the agent instance up after finishing
        mMustKillAgent = false;
    }

    //for adb restore
    FullRestoreEngineThread(FullRestoreEngine engine, InputStream inputStream) {
        mEngine = engine;
        engine.setRunning(true);
        mEngineStream = inputStream;
        // philippov: in adb agent is killed after restore.
        mMustKillAgent = true;
    }

    public boolean isRunning() {
        return mEngine.isRunning();
    }

    public int waitForResult() {
        return mEngine.waitForResult();
    }

    @Override
    public void run() {
        try {
            while (mEngine.isRunning()) {
                mEngine.restoreOneFile(mEngineStream, mMustKillAgent, mEngine.mBuffer,
                        mEngine.mOnlyPackage, mEngine.mAllowApks, mEngine.mEphemeralOpToken,
                        mEngine.mMonitor);
            }
        } finally {
            // Because mEngineStream adopted its underlying FD, this also
            // closes this end of the pipe.
            IoUtils.closeQuietly(mEngineStream);
        }
    }

    public void handleTimeout() {
        IoUtils.closeQuietly(mEngineStream);
        mEngine.handleTimeout();
    }
}
+7 −478

File changed.

Preview size limit exceeded, changes collapsed.

+3 −47
Original line number Diff line number Diff line
@@ -841,7 +841,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {

        final String TAG = "StreamFeederThread";
        FullRestoreEngine mEngine;
        EngineThread mEngineThread;
        FullRestoreEngineThread mEngineThread;

        // pipe through which we read data from the transport. [0] read, [1] write
        ParcelFileDescriptor[] mTransportPipes;
@@ -867,8 +867,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
                    mCurrentPackage.packageName);

            mEngine = new FullRestoreEngine(backupManagerService, this, null,
                    mMonitor, mCurrentPackage, false, false, mEphemeralOpToken);
            mEngineThread = new EngineThread(mEngine, mEnginePipes[0]);
                    mMonitor, mCurrentPackage, false, false, mEphemeralOpToken, false);
            mEngineThread = new FullRestoreEngineThread(mEngine, mEnginePipes[0]);

            ParcelFileDescriptor eWriteEnd = mEnginePipes[1];
            ParcelFileDescriptor tReadEnd = mTransportPipes[0];
@@ -1031,50 +1031,6 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
        }
    }

    class EngineThread implements Runnable {

        FullRestoreEngine mEngine;
        FileInputStream mEngineStream;

        EngineThread(FullRestoreEngine engine, ParcelFileDescriptor engineSocket) {
            mEngine = engine;
            engine.setRunning(true);
            // We *do* want this FileInputStream to own the underlying fd, so that
            // when we are finished with it, it closes this end of the pipe in a way
            // that signals its other end.
            mEngineStream = new FileInputStream(engineSocket.getFileDescriptor(), true);
        }

        public boolean isRunning() {
            return mEngine.isRunning();
        }

        public int waitForResult() {
            return mEngine.waitForResult();
        }

        @Override
        public void run() {
            try {
                while (mEngine.isRunning()) {
                    // Tell it to be sure to leave the agent instance up after finishing
                    mEngine.restoreOneFile(mEngineStream, false, mEngine.mBuffer,
                            mEngine.mOnlyPackage, mEngine.mAllowApks, mEngine.mEphemeralOpToken,
                            mEngine.mMonitor);
                }
            } finally {
                // Because mEngineStream adopted its underlying FD, this also
                // closes this end of the pipe.
                IoUtils.closeQuietly(mEngineStream);
            }
        }

        public void handleTimeout() {
            IoUtils.closeQuietly(mEngineStream);
            mEngine.handleTimeout();
        }
    }

    // state FINAL : tear everything down and we're done.
    private void finalizeRestore() {
        if (MORE_DEBUG) {