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

Commit 865303fc authored by Shreyas Basarge's avatar Shreyas Basarge
Browse files

API to select backup transport

This cl adds an API to select a backup
transport by its component name and
receive a callback when BackupManager
is bound to the transport. Calling this API
will make BackupManager bind to the transport
if it isn't already bound to it.

Also fixes the issue where BackupManager would
detect only one transport per package.

Ref: go/backup-transport-switching

Bug: 33616220
Test: Manually tested. GTS tests will be put up shortly.

Change-Id: I8c23bdbb84ceb05eb1fad9b3a8b9c4441cb06c74
parent 1628b97e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ LOCAL_SRC_FILES += \
	core/java/android/app/backup/IFullBackupRestoreObserver.aidl \
	core/java/android/app/backup/IRestoreObserver.aidl \
	core/java/android/app/backup/IRestoreSession.aidl \
	core/java/android/app/backup/ISelectBackupTransportCallback.aidl \
	core/java/android/app/usage/IStorageStatsManager.aidl \
	core/java/android/app/usage/IUsageStatsManager.aidl \
	core/java/android/bluetooth/IBluetooth.aidl \
+10 −1
Original line number Diff line number Diff line
@@ -6768,15 +6768,18 @@ package android.app.backup {
    method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver);
    method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver, int);
    method public int requestRestore(android.app.backup.RestoreObserver);
    method public java.lang.String selectBackupTransport(java.lang.String);
    method public deprecated java.lang.String selectBackupTransport(java.lang.String);
    method public void selectBackupTransport(android.content.ComponentName, android.app.backup.SelectBackupTransportCallback);
    method public void setAutoRestore(boolean);
    method public void setBackupEnabled(boolean);
    field public static final int ERROR_AGENT_FAILURE = -1003; // 0xfffffc15
    field public static final int ERROR_BACKUP_NOT_ALLOWED = -2001; // 0xfffff82f
    field public static final int ERROR_PACKAGE_NOT_FOUND = -2002; // 0xfffff82e
    field public static final int ERROR_TRANSPORT_ABORTED = -1000; // 0xfffffc18
    field public static final int ERROR_TRANSPORT_INVALID = -2; // 0xfffffffe
    field public static final int ERROR_TRANSPORT_PACKAGE_REJECTED = -1002; // 0xfffffc16
    field public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED = -1005; // 0xfffffc13
    field public static final int ERROR_TRANSPORT_UNAVAILABLE = -1; // 0xffffffff
    field public static final int FLAG_NON_INCREMENTAL_BACKUP = 1; // 0x1
    field public static final java.lang.String PACKAGE_MANAGER_SENTINEL = "@pm@";
    field public static final int SUCCESS = 0; // 0x0
@@ -6891,6 +6894,12 @@ package android.app.backup {
    field public long token;
  }
  public abstract class SelectBackupTransportCallback {
    ctor public SelectBackupTransportCallback();
    method public void onFailure(int);
    method public void onSuccess(java.lang.String);
  }
  public class SharedPreferencesBackupHelper extends android.app.backup.FileBackupHelperBase implements android.app.backup.BackupHelper {
    ctor public SharedPreferencesBackupHelper(android.content.Context, java.lang.String...);
    method public void performBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor);
+65 −6
Original line number Diff line number Diff line
@@ -18,20 +18,24 @@ package com.android.commands.bmgr;

import android.app.backup.BackupManager;
import android.app.backup.BackupProgress;
import android.app.backup.RestoreSet;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupObserver;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.RestoreSet;
import android.app.backup.ISelectBackupTransportCallback;
import android.content.ComponentName;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public final class Bmgr {
    IBackupManager mBmgr;
@@ -363,6 +367,11 @@ public final class Bmgr {
                return;
            }

            if ("-c".equals(which)) {
                doTransportByComponent();
                return;
            }

            String old = mBmgr.selectBackupTransport(which);
            if (old == null) {
                System.out.println("Unknown transport '" + which
@@ -370,12 +379,50 @@ public final class Bmgr {
            } else {
                System.out.println("Selected transport " + which + " (formerly " + old + ")");
            }

        } catch (RemoteException e) {
            System.err.println(e.toString());
            System.err.println(BMGR_NOT_RUNNING_ERR);
        }
    }

    private void doTransportByComponent() {
        String which = nextArg();
        if (which == null) {
            showUsage();
            return;
        }

        final CountDownLatch latch = new CountDownLatch(1);

        try {
            mBmgr.selectBackupTransportAsync(ComponentName.unflattenFromString(which),
                    new ISelectBackupTransportCallback.Stub() {
                        @Override
                        public void onSuccess(String transportName) {
                            System.out.println("Success. Selected transport: " + transportName);
                            latch.countDown();
                        }

                        @Override
                        public void onFailure(int reason) {
                            System.err.println("Failure. error=" + reason);
                            latch.countDown();
                        }
                    });
        } catch (RemoteException e) {
            System.err.println(e.toString());
            System.err.println(BMGR_NOT_RUNNING_ERR);
            return;
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            System.err.println("Operation interrupted.");
        }
    }

    private void doWipe() {
        String transport = nextArg();
        if (transport == null) {
@@ -427,7 +474,16 @@ public final class Bmgr {
    }

    private void doListTransports() {
        String arg = nextArg();

        try {
            if ("-c".equals(arg)) {
                for (ComponentName transport : mBmgr.listAllTransportComponents()) {
                    System.out.println(transport.flattenToShortString());
                }
                return;
            }

            String current = mBmgr.getCurrentTransport();
            String[] transports = mBmgr.listAllTransports();
            if (transports == null || transports.length == 0) {
@@ -649,9 +705,9 @@ public final class Bmgr {
        System.err.println("       bmgr backup PACKAGE");
        System.err.println("       bmgr enable BOOL");
        System.err.println("       bmgr enabled");
        System.err.println("       bmgr list transports");
        System.err.println("       bmgr list transports [-c]");
        System.err.println("       bmgr list sets");
        System.err.println("       bmgr transport WHICH");
        System.err.println("       bmgr transport WHICH|-c WHICH_COMPONENT");
        System.err.println("       bmgr restore TOKEN");
        System.err.println("       bmgr restore TOKEN PACKAGE...");
        System.err.println("       bmgr restore PACKAGE");
@@ -673,15 +729,18 @@ public final class Bmgr {
        System.err.println("the backup mechanism.");
        System.err.println("");
        System.err.println("The 'list transports' command reports the names of the backup transports");
        System.err.println("currently available on the device.  These names can be passed as arguments");
        System.err.println("BackupManager is currently bound to. These names can be passed as arguments");
        System.err.println("to the 'transport' and 'wipe' commands.  The currently active transport");
        System.err.println("is indicated with a '*' character.");
        System.err.println("is indicated with a '*' character. If -c flag is used, all available");
        System.err.println("transport components on the device are listed. These can be used with");
        System.err.println("the component variant of 'transport' command.");
        System.err.println("");
        System.err.println("The 'list sets' command reports the token and name of each restore set");
        System.err.println("available to the device via the currently active transport.");
        System.err.println("");
        System.err.println("The 'transport' command designates the named transport as the currently");
        System.err.println("active one.  This setting is persistent across reboots.");
        System.err.println("active one.  This setting is persistent across reboots. If -c flag is");
        System.err.println("specified, the following string is treated as a component name.");
        System.err.println("");
        System.err.println("The 'restore' command when given just a restore token initiates a full-system");
        System.err.println("restore operation from the currently active transport.  It will deliver");
+85 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app.backup;

import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
@@ -157,6 +158,25 @@ public class BackupManager {
    @SystemApi
    public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";


    /**
     * This error code is passed to {@link SelectBackupTransportCallback#onFailure(int)}
     * if the requested transport is unavailable.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_TRANSPORT_UNAVAILABLE = -1;

    /**
     * This error code is passed to {@link SelectBackupTransportCallback#onFailure(int)} if the
     * requested transport is not a valid BackupTransport.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_TRANSPORT_INVALID = -2;

    private Context mContext;
    private static IBackupManager sService;

@@ -390,17 +410,20 @@ public class BackupManager {
    }

    /**
     * Specify the current backup transport.  Callers must hold the
     * android.permission.BACKUP permission to use this method.
     * Specify the current backup transport.
     *
     * <p> Callers must hold the android.permission.BACKUP permission to use this method.
     *
     * @param transport The name of the transport to select.  This should be one
     *   of the names returned by {@link #listAllTransports()}.
     *   of the names returned by {@link #listAllTransports()}. This is the String returned by
     *   {@link BackupTransport#name()} for the particular transport.
     * @return The name of the previously selected transport.  If the given transport
     *   name is not one of the currently available transports, no change is made to
     *   the current transport setting and the method returns null.
     *
     * @hide
     */
    @Deprecated
    @SystemApi
    public String selectBackupTransport(String transport) {
        checkServiceBinder();
@@ -414,6 +437,34 @@ public class BackupManager {
        return null;
    }

    /**
     * Specify the current backup transport and get notified when the transport is ready to be used.
     * This method is async because BackupManager might need to bind to the specified transport
     * which is in a separate process.
     *
     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
     *
     * @param transport ComponentName of the service hosting the transport. This is different from
     *                  the transport's name that is returned by {@link BackupTransport#name()}.
     * @param listener A listener object to get a callback on the transport being selected.
     *
     * @hide
     */
    @SystemApi
    public void selectBackupTransport(ComponentName transport,
            SelectBackupTransportCallback listener) {
        checkServiceBinder();
        if (sService != null) {
            try {
                SelectTransportListenerWrapper wrapper = listener == null ?
                        null : new SelectTransportListenerWrapper(mContext, listener);
                sService.selectBackupTransportAsync(transport, wrapper);
            } catch (RemoteException e) {
                Log.e(TAG, "selectBackupTransportAsync() couldn't connect");
            }
        }
    }

    /**
     * Schedule an immediate backup attempt for all pending key/value updates.  This
     * is primarily intended for transports to use when they detect a suitable
@@ -598,4 +649,35 @@ public class BackupManager {
                mHandler.obtainMessage(MSG_FINISHED, status, 0));
        }
    }

    private class SelectTransportListenerWrapper extends ISelectBackupTransportCallback.Stub {

        private final Handler mHandler;
        private final SelectBackupTransportCallback mListener;

        SelectTransportListenerWrapper(Context context, SelectBackupTransportCallback listener) {
            mHandler = new Handler(context.getMainLooper());
            mListener = listener;
        }

        @Override
        public void onSuccess(final String transportName) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mListener.onSuccess(transportName);
                }
            });
        }

        @Override
        public void onFailure(final int reason) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mListener.onFailure(reason);
                }
            });
        }
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -19,8 +19,10 @@ package android.app.backup;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
import android.os.ParcelFileDescriptor;
import android.content.Intent;
import android.content.ComponentName;

/**
 * Direct interface to the Backup Manager Service that applications invoke on.  The only
@@ -217,6 +219,8 @@ interface IBackupManager {
     */
    String[] listAllTransports();

    ComponentName[] listAllTransportComponents();

    /**
     * Retrieve the list of whitelisted transport components.  Callers do </i>not</i> need
     * any special permission.
@@ -237,6 +241,21 @@ interface IBackupManager {
     */
    String selectBackupTransport(String transport);

    /**
     * Specify the current backup transport and get notified when the transport is ready to be used.
     * This method is async because BackupManager might need to bind to the specified transport
     * which is in a separate process.
     *
     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
     *
     * @param transport ComponentName of the service hosting the transport. This is different from
     *                  the transport's name that is returned by {@link BackupTransport#name()}.
     * @param listener A listener object to get a callback on the transport being selected.
     *
     * @hide
     */
    void selectBackupTransportAsync(in ComponentName transport, ISelectBackupTransportCallback listener);

    /**
     * Get the configuration Intent, if any, from the given transport.  Callers must
     * hold the android.permission.BACKUP permission in order to use this method.
Loading