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

Commit a9ac0b8b authored by Joël Stemmer's avatar Joël Stemmer Committed by Android (Google) Code Review
Browse files

Merge "Add additional parameters to `doRestoreFile` to IBackupAgent.aidl" into main

parents ef208724 986096c2
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -168,10 +168,19 @@ oneway interface IBackupAgent {
     *        contents.
     * @param callbackBinder Binder on which to indicate operation completion,
     *        passed here as a convenience to the agent.
     * @param appVersionCode The android:versionCode attribute of the application
     *        that created this data set.  This can help the agent distinguish among
     *        various historical backup content possibilities.
     * @param transportFlags Flags with additional information about the transport.
     * @param contentVersion A string that may have been provided by the application
     *        that created this data set. Typically used when appVersionCode was not
     *        available (e.g. for a cross-platform transfer).  This can help the agent
     *        decide how to interpret the backup content.
     */
    void doRestoreFile(in ParcelFileDescriptor data, long size,
            int type, String domain, String path, long mode, long mtime,
            int token, IBackupManager callbackBinder);
            int token, IBackupManager callbackBinder, long appVersionCode,
            int transportFlags, String contentVersion);

    /**
     * Provide the app with a canonical "all data has been delivered" end-of-restore
+43 −7
Original line number Diff line number Diff line
@@ -1115,7 +1115,10 @@ public abstract class BackupAgent extends ContextWrapper {
            String domain,
            String path,
            long mode,
            long mtime)
            long mtime,
            long appVersionCode,
            int transportFlags,
            String contentVersion)
            throws IOException {
        String basePath = null;

@@ -1133,7 +1136,13 @@ public abstract class BackupAgent extends ContextWrapper {
                            + " mode="
                            + mode
                            + " mtime="
                            + mtime);
                            + mtime
                            + " appVersionCode="
                            + appVersionCode
                            + " transportFlags="
                            + transportFlags
                            + " contentVersion="
                            + contentVersion);
        }

        basePath =
@@ -1158,9 +1167,9 @@ public abstract class BackupAgent extends ContextWrapper {
                                    type,
                                    mode,
                                    mtime,
                                    /* appVersionCode= */ 0,
                                    /* transportFlags= */ 0,
                                    /* contentVersion= */ ""));
                                    appVersionCode,
                                    transportFlags,
                                    contentVersion));
                } else {
                    onRestoreFile(data, size, outFile, type, mode, mtime);
                }
@@ -1465,11 +1474,38 @@ public abstract class BackupAgent extends ContextWrapper {
                long mode,
                long mtime,
                int token,
                IBackupManager callbackBinder)
                IBackupManager callbackBinder,
                long appVersionCode,
                int transportFlags,
                String contentVersion)
                throws RemoteException {
            final long ident = Binder.clearCallingIdentity();
            try {
                BackupAgent.this.onRestoreFile(data, size, type, domain, path, mode, mtime);
                if (Flags.enableCrossPlatformTransfer()) {
                    BackupAgent.this.onRestoreFile(
                            data,
                            size,
                            type,
                            domain,
                            path,
                            mode,
                            mtime,
                            appVersionCode,
                            transportFlags,
                            contentVersion);
                } else {
                    BackupAgent.this.onRestoreFile(
                            data,
                            size,
                            type,
                            domain,
                            path,
                            mode,
                            mtime,
                            /* appVersionCode= */ 0,
                            /* transportFlags= */ 0,
                            /* contentVersion= */ "");
                }
            } catch (IOException e) {
                Log.d(
                        TAG,
+136 −4
Original line number Diff line number Diff line
@@ -35,7 +35,9 @@ import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArraySet;

import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.server.backup.Flags;

@@ -46,6 +48,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -63,13 +66,15 @@ public class BackupAgentTest {

    @Mock IBackupManager mIBackupManager;
    @Mock FullBackup.BackupScheme mBackupScheme;
    @Mock Context mContext;

    private Context mContext;

    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = InstrumentationRegistry.getInstrumentation().getContext();
    }

    @Test
@@ -172,7 +177,10 @@ public class BackupAgentTest {
                /* mode= */ 0666,
                /* mtime= */ 12345,
                /* token= */ 6789,
                mIBackupManager);
                mIBackupManager,
                /* appVersionCode= */ 0,
                /* transportFlags= */ 0,
                /* contentVersion= */ "");

        try (FileInputStream in = new FileInputStream(pipes[0].getFileDescriptor())) {
            assertThat(in.available()).isEqualTo(0);
@@ -182,6 +190,92 @@ public class BackupAgentTest {
        }
    }

    @Test
    @DisableFlags({Flags.FLAG_ENABLE_CROSS_PLATFORM_TRANSFER})
    public void doRestoreFile_flagOff_doesNotSetExtraParams() throws Exception {
        TestWhichOnRestoreFileCalledBackupAgent agent =
                new TestWhichOnRestoreFileCalledBackupAgent();
        agent.attach(mContext);
        agent.onCreate(USER_HANDLE, BackupDestination.DEVICE_TRANSFER, OperationType.RESTORE);
        IBackupAgent agentBinder = (IBackupAgent) agent.onBind();
        long appVersionCode = 1;
        int transportFlags = BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER;
        String contentVersion = "1.0";

        ParcelFileDescriptor[] pipes = ParcelFileDescriptor.createPipe();
        FileOutputStream writeSide = new FileOutputStream(pipes[1].getFileDescriptor());
        writeSide.write("Hello".getBytes(StandardCharsets.UTF_8));

        agentBinder.doRestoreFile(
                pipes[0],
                /* length= */ 5,
                BackupAgent.TYPE_FILE,
                FullBackup.FILES_TREE_TOKEN,
                /* path= */ "hello_file",
                /* mode= */ 0666,
                /* mtime= */ 12345,
                /* token= */ 6789,
                mIBackupManager,
                appVersionCode,
                transportFlags,
                contentVersion);

        assertThat(agent.mOldOnRestoreFileCalled).isTrue();
        assertThat(agent.mNewOnRestoreFileCalled).isFalse();
        assertThat(agent.mAppVersionCodeReceived).isEqualTo(0);
        assertThat(agent.mTransportFlagsReceived).isEqualTo(0);
        assertThat(agent.mContentVersionReceived).isEqualTo("");
        try (FileInputStream in = new FileInputStream(pipes[0].getFileDescriptor())) {
            assertThat(in.available()).isEqualTo(0);
        } finally {
            pipes[0].close();
            pipes[1].close();
        }
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_CROSS_PLATFORM_TRANSFER})
    public void doRestoreFile_flagOn_setsExtraParams() throws Exception {
        TestWhichOnRestoreFileCalledBackupAgent agent =
                new TestWhichOnRestoreFileCalledBackupAgent();
        agent.attach(mContext);
        agent.onCreate(USER_HANDLE, BackupDestination.DEVICE_TRANSFER, OperationType.RESTORE);
        IBackupAgent agentBinder = (IBackupAgent) agent.onBind();
        long appVersionCode = 1;
        int transportFlags = BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER;
        String contentVersion = "1.0";

        ParcelFileDescriptor[] pipes = ParcelFileDescriptor.createPipe();
        FileOutputStream writeSide = new FileOutputStream(pipes[1].getFileDescriptor());
        writeSide.write("Hello".getBytes(StandardCharsets.UTF_8));

        agentBinder.doRestoreFile(
                pipes[0],
                /* length= */ 5,
                BackupAgent.TYPE_FILE,
                FullBackup.FILES_TREE_TOKEN,
                /* path= */ "hello_file",
                /* mode= */ 0666,
                /* mtime= */ 12345,
                /* token= */ 6789,
                mIBackupManager,
                appVersionCode,
                transportFlags,
                contentVersion);

        assertThat(agent.mOldOnRestoreFileCalled).isFalse();
        assertThat(agent.mNewOnRestoreFileCalled).isTrue();
        assertThat(agent.mAppVersionCodeReceived).isEqualTo(appVersionCode);
        assertThat(agent.mTransportFlagsReceived).isEqualTo(transportFlags);
        assertThat(agent.mContentVersionReceived).isEqualTo(contentVersion);
        try (FileInputStream in = new FileInputStream(pipes[0].getFileDescriptor())) {
            assertThat(in.available()).isEqualTo(0);
        } finally {
            pipes[0].close();
            pipes[1].close();
        }
    }

    @Test
    @DisableFlags({Flags.FLAG_ENABLE_CROSS_PLATFORM_TRANSFER})
    public void doMeasureFullBackup_flagOff_callOnFullBackup() throws Exception {
@@ -257,7 +351,6 @@ public class BackupAgentTest {
    }

    private static class TestRestoreIgnoringFullBackupAgent extends TestFullBackupAgent {

        @Override
        protected void onRestoreFile(
                ParcelFileDescriptor data,
@@ -266,12 +359,51 @@ public class BackupAgentTest {
                String domain,
                String path,
                long mode,
                long mtime)
                long mtime,
                long appVersionCode,
                int transportFlags,
                String contentVersion)
                throws IOException {
            // Ignore the file and don't consume any data.
        }
    }

    private static class TestWhichOnRestoreFileCalledBackupAgent extends TestFullBackupAgent {
        boolean mOldOnRestoreFileCalled = false;
        boolean mNewOnRestoreFileCalled = false;
        long mAppVersionCodeReceived = 0;
        int mTransportFlagsReceived = 0;
        String mContentVersionReceived = "";

        @Override
        public void onRestoreFile(
                ParcelFileDescriptor data,
                long size,
                File destination,
                int type,
                long mode,
                long mtime)
                throws IOException {
            mOldOnRestoreFileCalled = true;
            FullBackup.restoreFile(data, size, type, mode, mtime, null);
        }

        @Override
        public void onRestoreFile(@NonNull FullRestoreDataInput data) throws IOException {
            mNewOnRestoreFileCalled = true;
            mAppVersionCodeReceived = data.getAppVersionCode();
            mTransportFlagsReceived = data.getTransportFlags();
            mContentVersionReceived = data.getContentVersion();
            FullBackup.restoreFile(
                    data.getData(),
                    data.getSize(),
                    data.getType(),
                    data.getMode(),
                    data.getModificationTimeSeconds(),
                    null);
        }
    }

    private static class TestMeasureSizeBackupAgent extends BackupAgent {
        private final long mSize;
        private boolean mOnFullBackupCalled;
+2 −1
Original line number Diff line number Diff line
@@ -526,7 +526,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {

    @Override
    public void onRestoreFile(ParcelFileDescriptor data, long size,
            int type, String domain, String relpath, long mode, long mtime)
            int type, String domain, String relpath, long mode, long mtime,
            long appVersionCode, int transportFlags, String contentVersion)
            throws IOException {
        if (DEBUG_BACKUP) Log.d(TAG, "onRestoreFile() invoked");
        // Our data is actually a blob of flattened settings data identical to that
+24 −13
Original line number Diff line number Diff line
package com.android.sharedstoragebackup;

import android.app.backup.FullBackupAgent;
import android.app.backup.FullBackup;
import android.app.backup.FullBackupAgent;
import android.app.backup.FullBackupDataOutput;
import android.content.Context;
import android.os.Environment;
@@ -30,9 +30,7 @@ public class SharedStorageAgent extends FullBackupAgent {
        }
    }

    /**
     * Full backup of the shared-storage filesystem
     */
    /** Full backup of the shared-storage filesystem */
    @Override
    public void onFullBackup(FullBackupDataOutput output) throws IOException {
        // If there are shared-storage volumes available, run the inherited directory-
@@ -43,7 +41,9 @@ public class SharedStorageAgent extends FullBackupAgent {
            // Ignore all apps' getExternalFilesDir() content; it is backed up as part of
            // each app-specific payload.
            ArraySet<String> externalFilesDirFilter = new ArraySet();
            final File externalAndroidRoot = new File(Environment.getExternalStorageDirectory(),
            final File externalAndroidRoot =
                    new File(
                            Environment.getExternalStorageDirectory(),
                            Environment.DIRECTORY_ANDROID);
            externalFilesDirFilter.add(externalAndroidRoot.getCanonicalPath());

@@ -53,19 +53,30 @@ public class SharedStorageAgent extends FullBackupAgent {
                //     shared/N/path/to/file
                // The restore will then extract to the given volume
                String domain = FullBackup.SHARED_PREFIX + i;
                fullBackupFileTree(null, domain, v.getPath(),
                fullBackupFileTree(
                        null,
                        domain,
                        v.getPath(),
                        null /* manifestExcludes */,
                        externalFilesDirFilter /* systemExcludes */, output);
                        externalFilesDirFilter /* systemExcludes */,
                        output);
            }
        }
    }

    /**
     * Full restore of one file to shared storage
     */
    /** Full restore of one file to shared storage */
    @Override
    public void onRestoreFile(ParcelFileDescriptor data, long size,
            int type, String domain, String relpath, long mode, long mtime)
    public void onRestoreFile(
            ParcelFileDescriptor data,
            long size,
            int type,
            String domain,
            String relpath,
            long mode,
            long mtime,
            long appVersionCode,
            int transportFlags,
            String contentVersion)
            throws IOException {
        if (DEBUG) Slog.d(TAG, "Shared restore: [ " + domain + " : " + relpath + "]");

Loading