/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.backup;

import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;

/**
 * The interface through which an application interacts with the Android backup service to
 * request backup and restore operations.
 * Applications instantiate it using the constructor and issue calls through that instance.
 * <p>
 * When an application has made changes to data which should be backed up, a
 * call to {@link #dataChanged()} will notify the backup service. The system
 * will then schedule a backup operation to occur in the near future. Repeated
 * calls to {@link #dataChanged()} have no further effect until the backup
 * operation actually occurs.
 * <p>
 * A backup or restore operation for your application begins when the system launches the
 * {@link android.app.backup.BackupAgent} subclass you've declared in your manifest. See the
 * documentation for {@link android.app.backup.BackupAgent} for a detailed description
 * of how the operation then proceeds.
 * <p>
 * Several attributes affecting the operation of the backup and restore mechanism
 * can be set on the <code>
 * <a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
 * tag in your application's AndroidManifest.xml file.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about using BackupManager, read the
 * <a href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p></div>
 *
 * @attr ref android.R.styleable#AndroidManifestApplication_allowBackup
 * @attr ref android.R.styleable#AndroidManifestApplication_backupAgent
 * @attr ref android.R.styleable#AndroidManifestApplication_killAfterRestore
 * @attr ref android.R.styleable#AndroidManifestApplication_restoreAnyVersion
 */
public class BackupManager {
    private static final String TAG = "BackupManager";

    // BackupObserver status codes
    /**
     * Indicates that backup succeeded.
     *
     * @hide
     */
    @SystemApi
    public static final int SUCCESS = 0;

    /**
     * Indicates that backup is either not enabled at all or
     * backup for the package was rejected by backup service
     * or backup transport,
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_BACKUP_NOT_ALLOWED = -2001;

    /**
     * The requested app is not installed on the device.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_PACKAGE_NOT_FOUND = -2002;

    /**
     * The backup operation was cancelled.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_BACKUP_CANCELLED = -2003;

    /**
     * The transport for some reason was not in a good state and
     * aborted the entire backup request. This is a transient
     * failure and should not be retried immediately.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_TRANSPORT_ABORTED = BackupTransport.TRANSPORT_ERROR;

    /**
     * Returned when the transport was unable to process the
     * backup request for a given package, for example if the
     * transport hit a transient network failure. The remaining
     * packages provided to {@link #requestBackup(String[], BackupObserver)}
     * will still be attempted.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_TRANSPORT_PACKAGE_REJECTED =
            BackupTransport.TRANSPORT_PACKAGE_REJECTED;

    /**
     * Returned when the transport reject the attempt to backup because
     * backup data size exceeded current quota limit for this package.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED =
            BackupTransport.TRANSPORT_QUOTA_EXCEEDED;

    /**
     * The {@link BackupAgent} for the requested package failed for some reason
     * and didn't provide appropriate backup data.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_AGENT_FAILURE = BackupTransport.AGENT_ERROR;

    /**
     * Intent extra when any subsidiary backup-related UI is launched from Settings:  does
     * device policy or configuration permit backup operations to run at all?
     *
     * @hide
     */
    public static final String EXTRA_BACKUP_SERVICES_AVAILABLE = "backup_services_available";

    /**
     * If this flag is passed to {@link #requestBackup(String[], BackupObserver, int)},
     * BackupManager will pass a blank old state to BackupAgents of requested packages.
     *
     * @hide
     */
    @SystemApi
    public static final int FLAG_NON_INCREMENTAL_BACKUP = 1;

    /**
     * Use with {@link #requestBackup} to force backup of
     * package meta data. Typically you do not need to explicitly request this be backed up as it is
     * handled internally by the BackupManager. If you are requesting backups with
     * FLAG_NON_INCREMENTAL, this package won't automatically be backed up and you have to
     * explicitly request for its backup.
     *
     * @hide
     */
    @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;

    private static void checkServiceBinder() {
        if (sService == null) {
            sService = IBackupManager.Stub.asInterface(
                    ServiceManager.getService(Context.BACKUP_SERVICE));
        }
    }

    /**
     * Constructs a BackupManager object through which the application can
     * communicate with the Android backup system.
     *
     * @param context The {@link android.content.Context} that was provided when
     *                one of your application's {@link android.app.Activity Activities}
     *                was created.
     */
    public BackupManager(Context context) {
        mContext = context;
    }

    /**
     * Notifies the Android backup system that your application wishes to back up
     * new changes to its data.  A backup operation using your application's
     * {@link android.app.backup.BackupAgent} subclass will be scheduled when you
     * call this method.
     */
    public void dataChanged() {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.dataChanged(mContext.getPackageName());
            } catch (RemoteException e) {
                Log.d(TAG, "dataChanged() couldn't connect");
            }
        }
    }

    /**
     * Convenience method for callers who need to indicate that some other package
     * needs a backup pass.  This can be useful in the case of groups of packages
     * that share a uid.
     * <p>
     * This method requires that the application hold the "android.permission.BACKUP"
     * permission if the package named in the argument does not run under the same uid
     * as the caller.
     *
     * @param packageName The package name identifying the application to back up.
     */
    public static void dataChanged(String packageName) {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.dataChanged(packageName);
            } catch (RemoteException e) {
                Log.e(TAG, "dataChanged(pkg) couldn't connect");
            }
        }
    }

    /**
     * @deprecated Since Android P app can no longer request restoring of its backup.
     *
     * Restore the calling application from backup.  The data will be restored from the
     * current backup dataset if the application has stored data there, or from
     * the dataset used during the last full device setup operation if the current
     * backup dataset has no matching data.  If no backup data exists for this application
     * in either source, a nonzero value will be returned.
     *
     * <p>If this method returns zero (meaning success), the OS will attempt to retrieve
     * a backed-up dataset from the remote transport, instantiate the application's
     * backup agent, and pass the dataset to the agent's
     * {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) onRestore()}
     * method.
     *
     * @param observer The {@link RestoreObserver} to receive callbacks during the restore
     * operation. This must not be null.
     *
     * @return Zero on success; nonzero on error.
     */
    @Deprecated
    public int requestRestore(RestoreObserver observer) {
        return requestRestore(observer, null);
    }

    // system APIs start here

    /**
     * @deprecated Since Android P app can no longer request restoring of its backup.
     *
     * Restore the calling application from backup.  The data will be restored from the
     * current backup dataset if the application has stored data there, or from
     * the dataset used during the last full device setup operation if the current
     * backup dataset has no matching data.  If no backup data exists for this application
     * in either source, a nonzero value will be returned.
     *
     * <p>If this method returns zero (meaning success), the OS will attempt to retrieve
     * a backed-up dataset from the remote transport, instantiate the application's
     * backup agent, and pass the dataset to the agent's
     * {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) onRestore()}
     * method.
     *
     * @param observer The {@link RestoreObserver} to receive callbacks during the restore
     * operation. This must not be null.
     *
     * @param monitor the {@link BackupManagerMonitor} to receive callbacks during the restore
     * operation.
     *
     * @return Zero on success; nonzero on error.
     *
     * @hide
     */
    @Deprecated
    @SystemApi
    public int requestRestore(RestoreObserver observer, BackupManagerMonitor monitor) {
        Log.w(TAG, "requestRestore(): Since Android P app can no longer request restoring"
                + " of its backup.");
        return -1;
    }

    /**
     * Begin the process of restoring data from backup.  See the
     * {@link android.app.backup.RestoreSession} class for documentation on that process.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public RestoreSession beginRestoreSession() {
        RestoreSession session = null;
        checkServiceBinder();
        if (sService != null) {
            try {
                // All packages, current transport
                IRestoreSession binder = sService.beginRestoreSession(null, null);
                if (binder != null) {
                    session = new RestoreSession(mContext, binder);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "beginRestoreSession() couldn't connect");
            }
        }
        return session;
    }

    /**
     * Enable/disable the backup service entirely.  When disabled, no backup
     * or restore operations will take place.  Data-changed notifications will
     * still be observed and collected, however, so that changes made while the
     * mechanism was disabled will still be backed up properly if it is enabled
     * at some point in the future.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public void setBackupEnabled(boolean isEnabled) {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.setBackupEnabled(isEnabled);
            } catch (RemoteException e) {
                Log.e(TAG, "setBackupEnabled() couldn't connect");
            }
        }
    }

    /**
     * Report whether the backup mechanism is currently enabled.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public boolean isBackupEnabled() {
        checkServiceBinder();
        if (sService != null) {
            try {
                return sService.isBackupEnabled();
            } catch (RemoteException e) {
                Log.e(TAG, "isBackupEnabled() couldn't connect");
            }
        }
        return false;
    }

    /**
     * Report whether the backup mechanism is currently active.
     * When it is inactive, the device will not perform any backup operations, nor will it
     * deliver data for restore, although clients can still safely call BackupManager methods.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public boolean isBackupServiceActive(UserHandle user) {
        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
                "isBackupServiceActive");
        checkServiceBinder();
        if (sService != null) {
            try {
                return sService.isBackupServiceActive(user.getIdentifier());
            } catch (RemoteException e) {
                Log.e(TAG, "isBackupEnabled() couldn't connect");
            }
        }
        return false;
    }

    /**
     * Enable/disable data restore at application install time.  When enabled, app
     * installation will include an attempt to fetch the app's historical data from
     * the archival restore dataset (if any).  When disabled, no such attempt will
     * be made.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public void setAutoRestore(boolean isEnabled) {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.setAutoRestore(isEnabled);
            } catch (RemoteException e) {
                Log.e(TAG, "setAutoRestore() couldn't connect");
            }
        }
    }

    /**
     * Identify the currently selected transport.
     * @return The name of the currently active backup transport.  In case of
     *   failure or if no transport is currently active, this method returns {@code null}.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public String getCurrentTransport() {
        checkServiceBinder();
        if (sService != null) {
            try {
                return sService.getCurrentTransport();
            } catch (RemoteException e) {
                Log.e(TAG, "getCurrentTransport() couldn't connect");
            }
        }
        return null;
    }

    /**
     * Request a list of all available backup transports' names.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public String[] listAllTransports() {
        checkServiceBinder();
        if (sService != null) {
            try {
                return sService.listAllTransports();
            } catch (RemoteException e) {
                Log.e(TAG, "listAllTransports() couldn't connect");
            }
        }
        return null;
    }

    /**
     * Update the attributes of the transport identified by {@code transportComponent}. If the
     * specified transport has not been bound at least once (for registration), this call will be
     * ignored. Only the host process of the transport can change its description, otherwise a
     * {@link SecurityException} will be thrown.
     *
     * @param transportComponent The identity of the transport being described.
     * @param name A {@link String} with the new name for the transport. This is NOT for
     *     identification. MUST NOT be {@code null}.
     * @param configurationIntent An {@link Intent} that can be passed to
     *     {@link Context#startActivity} in order to launch the transport's configuration UI. It may
     *     be {@code null} if the transport does not offer any user-facing configuration UI.
     * @param currentDestinationString A {@link String} describing the destination to which the
     *     transport is currently sending data. MUST NOT be {@code null}.
     * @param dataManagementIntent An {@link Intent} that can be passed to
     *     {@link Context#startActivity} in order to launch the transport's data-management UI. It
     *     may be {@code null} if the transport does not offer any user-facing data
     *     management UI.
     * @param dataManagementLabel A {@link String} to be used as the label for the transport's data
     *     management affordance. This MUST be {@code null} when dataManagementIntent is
     *     {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
     * @throws SecurityException If the UID of the calling process differs from the package UID of
     *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public void updateTransportAttributes(
            ComponentName transportComponent,
            String name,
            @Nullable Intent configurationIntent,
            String currentDestinationString,
            @Nullable Intent dataManagementIntent,
            @Nullable String dataManagementLabel) {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.updateTransportAttributes(
                        transportComponent,
                        name,
                        configurationIntent,
                        currentDestinationString,
                        dataManagementIntent,
                        dataManagementLabel);
            } catch (RemoteException e) {
                Log.e(TAG, "describeTransport() couldn't connect");
            }
        }
    }

    /**
     * Specify the current backup transport.
     *
     * @param transport The name of the transport to select.  This should be one
     *   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
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public String selectBackupTransport(String transport) {
        checkServiceBinder();
        if (sService != null) {
            try {
                return sService.selectBackupTransport(transport);
            } catch (RemoteException e) {
                Log.e(TAG, "selectBackupTransport() couldn't connect");
            }
        }
        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.
     *
     * @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
    @RequiresPermission(android.Manifest.permission.BACKUP)
    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
     * opportunity for doing a backup pass.  If there are no pending updates to
     * be sent, no action will be taken.  Even if some updates are pending, the
     * transport will still be asked to confirm via the usual requestBackupTime()
     * method.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public void backupNow() {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.backupNow();
            } catch (RemoteException e) {
                Log.e(TAG, "backupNow() couldn't connect");
            }
        }
    }

    /**
     * Ask the framework which dataset, if any, the given package's data would be
     * restored from if we were to install it right now.
     *
     * @param packageName The name of the package whose most-suitable dataset we
     *     wish to look up
     * @return The dataset token from which a restore should be attempted, or zero if
     *     no suitable data is available.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public long getAvailableRestoreToken(String packageName) {
        checkServiceBinder();
        if (sService != null) {
            try {
                return sService.getAvailableRestoreToken(packageName);
            } catch (RemoteException e) {
                Log.e(TAG, "getAvailableRestoreToken() couldn't connect");
            }
        }
        return 0;
    }

    /**
     * Ask the framework whether this app is eligible for backup.
     *
     * @param packageName The name of the package.
     * @return Whether this app is eligible for backup.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public boolean isAppEligibleForBackup(String packageName) {
        checkServiceBinder();
        if (sService != null) {
            try {
                return sService.isAppEligibleForBackup(packageName);
            } catch (RemoteException e) {
                Log.e(TAG, "isAppEligibleForBackup(pkg) couldn't connect");
            }
        }
        return false;
    }
    
    /**
     * Request an immediate backup, providing an observer to which results of the backup operation
     * will be published. The Android backup system will decide for each package whether it will
     * be full app data backup or key/value-pair-based backup.
     *
     * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all
     * provided packages using the remote transport.
     *
     * @param packages List of package names to backup.
     * @param observer The {@link BackupObserver} to receive callbacks during the backup
     * operation. Could be {@code null}.
     * @return {@link BackupManager#SUCCESS} on success; nonzero on error.
     * @exception  IllegalArgumentException on null or empty {@code packages} param.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public int requestBackup(String[] packages, BackupObserver observer) {
        return requestBackup(packages, observer, null, 0);
    }

    /**
     * Request an immediate backup, providing an observer to which results of the backup operation
     * will be published. The Android backup system will decide for each package whether it will
     * be full app data backup or key/value-pair-based backup.
     *
     * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all
     * provided packages using the remote transport.
     *
     * @param packages List of package names to backup.
     * @param observer The {@link BackupObserver} to receive callbacks during the backup
     *                 operation. Could be {@code null}.
     * @param monitor  The {@link BackupManagerMonitorWrapper} to receive callbacks of important
     *                 events during the backup operation. Could be {@code null}.
     * @param flags    {@link #FLAG_NON_INCREMENTAL_BACKUP}.
     * @return {@link BackupManager#SUCCESS} on success; nonzero on error.
     * @throws IllegalArgumentException on null or empty {@code packages} param.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public int requestBackup(String[] packages, BackupObserver observer,
            BackupManagerMonitor monitor, int flags) {
        checkServiceBinder();
        if (sService != null) {
            try {
                BackupObserverWrapper observerWrapper = observer == null
                        ? null
                        : new BackupObserverWrapper(mContext, observer);
                BackupManagerMonitorWrapper monitorWrapper = monitor == null
                        ? null
                        : new BackupManagerMonitorWrapper(monitor);
                return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags);
            } catch (RemoteException e) {
                Log.e(TAG, "requestBackup() couldn't connect");
            }
        }
        return -1;
    }

    /**
     * Cancel all running backups. After this call returns, no currently running backups will
     * interact with the selected transport.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.BACKUP)
    public void cancelBackups() {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.cancelBackups();
            } catch (RemoteException e) {
                Log.e(TAG, "cancelBackups() couldn't connect.");
            }
        }
    }

    /*
     * We wrap incoming binder calls with a private class implementation that
     * redirects them into main-thread actions.  This serializes the backup
     * progress callbacks nicely within the usual main-thread lifecycle pattern.
     */
    private class BackupObserverWrapper extends IBackupObserver.Stub {
        final Handler mHandler;
        final BackupObserver mObserver;

        static final int MSG_UPDATE = 1;
        static final int MSG_RESULT = 2;
        static final int MSG_FINISHED = 3;

        BackupObserverWrapper(Context context, BackupObserver observer) {
            mHandler = new Handler(context.getMainLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case MSG_UPDATE:
                            Pair<String, BackupProgress> obj =
                                (Pair<String, BackupProgress>) msg.obj;
                            mObserver.onUpdate(obj.first, obj.second);
                            break;
                        case MSG_RESULT:
                            mObserver.onResult((String)msg.obj, msg.arg1);
                            break;
                        case MSG_FINISHED:
                            mObserver.backupFinished(msg.arg1);
                            break;
                        default:
                            Log.w(TAG, "Unknown message: " + msg);
                            break;
                    }
                }
            };
            mObserver = observer;
        }

        // Binder calls into this object just enqueue on the main-thread handler
        @Override
        public void onUpdate(String currentPackage, BackupProgress backupProgress) {
            mHandler.sendMessage(
                mHandler.obtainMessage(MSG_UPDATE, Pair.create(currentPackage, backupProgress)));
        }

        @Override
        public void onResult(String currentPackage, int status) {
            mHandler.sendMessage(
                mHandler.obtainMessage(MSG_RESULT, status, 0, currentPackage));
        }

        @Override
        public void backupFinished(int status) {
            mHandler.sendMessage(
                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);
                }
            });
        }
    }

    private class BackupManagerMonitorWrapper extends IBackupManagerMonitor.Stub {
        final BackupManagerMonitor mMonitor;

        BackupManagerMonitorWrapper(BackupManagerMonitor monitor) {
            mMonitor = monitor;
        }

        @Override
        public void onEvent(final Bundle event) throws RemoteException {
            mMonitor.onEvent(event);
        }
    }

}
