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

Commit 74318c98 authored by Christopher Tate's avatar Christopher Tate
Browse files

Provide stable concrete wrapper for backup transport API

This initial version is a simple pass-through of the existing
IBackupTransport AIDL definition.

Change-Id: I0f6c9ffc7101f82127ab61ba6cba9f5003af6a0c
parent 7d330757
Loading
Loading
Loading
Loading
+334 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.content.Intent;
import android.content.pm.PackageInfo;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;

import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.IBackupTransport;

/**
 * Concrete class that provides a stable-API bridge between IBackupTransport
 * and its implementations.
 *
 * @hide
 */
public class BackupTransport {
    IBackupTransport mBinderImpl = new TransportImpl();
    /** @hide */
    public IBinder getBinder() {
        return mBinderImpl.asBinder();
    }

    // ------------------------------------------------------------------------------------
    // Transport self-description and general configuration interfaces
    //

    /**
     * Ask the transport for the name under which it should be registered.  This will
     * typically be its host service's component name, but need not be.
     */
    public String name() {
        throw new UnsupportedOperationException("Transport name() not implemented");
    }

    /**
     * Ask the transport for an Intent that can be used to launch any internal
     * configuration Activity that it wishes to present.  For example, the transport
     * may offer a UI for allowing the user to supply login credentials for the
     * transport's off-device backend.
     *
     * If the transport does not supply any user-facing configuration UI, it should
     * return null from this method.
     *
     * @return An Intent that can be passed to Context.startActivity() in order to
     *         launch the transport's configuration UI.  This method will return null
     *         if the transport does not offer any user-facing configuration UI.
     */
    public Intent configurationIntent() {
        return null;
    }

    /**
     * On demand, supply a one-line string that can be shown to the user that
     * describes the current backend destination.  For example, a transport that
     * can potentially associate backup data with arbitrary user accounts should
     * include the name of the currently-active account here.
     *
     * @return A string describing the destination to which the transport is currently
     *         sending data.  This method should not return null.
     */
    public String currentDestinationString() {
        throw new UnsupportedOperationException(
                "Transport currentDestinationString() not implemented");
    }

    /**
     * Ask the transport where, on local device storage, to keep backup state blobs.
     * This is per-transport so that mock transports used for testing can coexist with
     * "live" backup services without interfering with the live bookkeeping.  The
     * returned string should be a name that is expected to be unambiguous among all
     * available backup transports; the name of the class implementing the transport
     * is a good choice.
     *
     * @return A unique name, suitable for use as a file or directory name, that the
     *         Backup Manager could use to disambiguate state files associated with
     *         different backup transports.
     */
    public String transportDirName() {
        throw new UnsupportedOperationException(
                "Transport transportDirName() not implemented");
    }

    // ------------------------------------------------------------------------------------
    // Key/value incremental backup support interfaces

    /**
     * Verify that this is a suitable time for a backup pass.  This should return zero
     * if a backup is reasonable right now, some positive value otherwise.  This method
     * will be called outside of the {@link #performBackup}/{@link #finishBackup} pair.
     *
     * <p>If this is not a suitable time for a backup, the transport should return a
     * backoff delay, in milliseconds, after which the Backup Manager should try again.
     *
     * @return Zero if this is a suitable time for a backup pass, or a positive time delay
     *   in milliseconds to suggest deferring the backup pass for a while.
     */
    public long requestBackupTime() {
        return 0;
    }

    /**
     * Initialize the server side storage for this device, erasing all stored data.
     * The transport may send the request immediately, or may buffer it.  After
     * this is called, {@link #finishBackup} will be called to ensure the request
     * is sent and received successfully.
     *
     * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far) or
     *   {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure).
     */
    public int initializeDevice() {
        return BackupConstants.TRANSPORT_ERROR;
    }

    /**
     * Send one application's key/value data update to the backup destination.  The
     * transport may send the data immediately, or may buffer it.  After this is called,
     * {@link #finishBackup} will be called to ensure the data is sent and recorded successfully.
     *
     * @param packageInfo The identity of the application whose data is being backed up.
     *   This specifically includes the signature list for the package.
     * @param data The data stream that resulted from invoking the application's
     *   BackupService.doBackup() method.  This may be a pipe rather than a file on
     *   persistent media, so it may not be seekable.
     * @param wipeAllFirst When true, <i>all</i> backed-up data for the current device/account
     *   must be erased prior to the storage of the data provided here.  The purpose of this
     *   is to provide a guarantee that no stale data exists in the restore set when the
     *   device begins providing incremental backups.
     * @return one of {@link BackupConstants#TRANSPORT_OK} (OK so far),
     *  {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure), or
     *  {@link BackupConstants#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has
     *  become lost due to inactivity purge or some other reason and needs re-initializing)
     */
    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) {
        return BackupConstants.TRANSPORT_ERROR;
    }

    /**
     * Erase the give application's data from the backup destination.  This clears
     * out the given package's data from the current backup set, making it as though
     * the app had never yet been backed up.  After this is called, {@link finishBackup}
     * must be called to ensure that the operation is recorded successfully.
     *
     * @return the same error codes as {@link #performBackup}.
     */
    public int clearBackupData(PackageInfo packageInfo) {
        return BackupConstants.TRANSPORT_ERROR;
    }

    /**
     * Finish sending application data to the backup destination.  This must be
     * called after {@link #performBackup} or {@link clearBackupData} to ensure that
     * all data is sent.  Only when this method returns true can a backup be assumed
     * to have succeeded.
     *
     * @return the same error codes as {@link #performBackup}.
     */
    public int finishBackup() {
        return BackupConstants.TRANSPORT_ERROR;
    }

    // ------------------------------------------------------------------------------------
    // Key/value dataset restore interfaces

    /**
     * Get the set of all backups currently available over this transport.
     *
     * @return Descriptions of the set of restore images available for this device,
     *   or null if an error occurred (the attempt should be rescheduled).
     **/
    public RestoreSet[] getAvailableRestoreSets() {
        return null;
    }

    /**
     * Get the identifying token of the backup set currently being stored from
     * this device.  This is used in the case of applications wishing to restore
     * their last-known-good data.
     *
     * @return A token that can be passed to {@link #startRestore}, or 0 if there
     *   is no backup set available corresponding to the current device state.
     */
    public long getCurrentRestoreSet() {
        return 0;
    }

    /**
     * Start restoring application data from backup.  After calling this function,
     * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
     * to walk through the actual application data.
     *
     * @param token A backup token as returned by {@link #getAvailableRestoreSets}
     *   or {@link #getCurrentRestoreSet}.
     * @param packages List of applications to restore (if data is available).
     *   Application data will be restored in the order given.
     * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call
     *   {@link #nextRestorePackage}) or {@link BackupConstants#TRANSPORT_ERROR}
     *   (an error occurred, the restore should be aborted and rescheduled).
     */
    public int startRestore(long token, PackageInfo[] packages) {
        return BackupConstants.TRANSPORT_ERROR;
    }

    /**
     * Get the package name of the next application with data in the backup store.
     *
     * @return The name of one of the packages supplied to {@link #startRestore},
     *   or "" (the empty string) if no more backup data is available,
     *   or null if an error occurred (the restore should be aborted and rescheduled).
     */
    public String nextRestorePackage() {
        return null;
    }

    /**
     * Get the data for the application returned by {@link #nextRestorePackage}.
     * @param data An open, writable file into which the backup data should be stored.
     * @return the same error codes as {@link #startRestore}.
     */
    public int getRestoreData(ParcelFileDescriptor outFd) {
        return BackupConstants.TRANSPORT_ERROR;
    }

    /**
     * End a restore session (aborting any in-process data transfer as necessary),
     * freeing any resources and connections used during the restore process.
     */
    public void finishRestore() {
        throw new UnsupportedOperationException(
                "Transport finishRestore() not implemented");
    }

    /**
     * Bridge between the actual IBackupTransport implementation and the stable API.  If the
     * binder interface needs to change, we use this layer to translate so that we can
     * (if appropriate) decouple those framework-side changes from the BackupTransport
     * implementations.
     */
    class TransportImpl extends IBackupTransport.Stub {

        @Override
        public String name() throws RemoteException {
            return BackupTransport.this.name();
        }

        @Override
        public Intent configurationIntent() throws RemoteException {
            return BackupTransport.this.configurationIntent();
        }

        @Override
        public String currentDestinationString() throws RemoteException {
            return BackupTransport.this.currentDestinationString();
        }

        @Override
        public String transportDirName() throws RemoteException {
            return BackupTransport.this.transportDirName();
        }

        @Override
        public long requestBackupTime() throws RemoteException {
            return BackupTransport.this.requestBackupTime();
        }

        @Override
        public int initializeDevice() throws RemoteException {
            return BackupTransport.this.initializeDevice();
        }

        @Override
        public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd)
                throws RemoteException {
            return BackupTransport.this.performBackup(packageInfo, inFd);
        }

        @Override
        public int clearBackupData(PackageInfo packageInfo) throws RemoteException {
            return BackupTransport.this.clearBackupData(packageInfo);
        }

        @Override
        public int finishBackup() throws RemoteException {
            return BackupTransport.this.finishBackup();
        }

        @Override
        public RestoreSet[] getAvailableRestoreSets() throws RemoteException {
            return BackupTransport.this.getAvailableRestoreSets();
        }

        @Override
        public long getCurrentRestoreSet() throws RemoteException {
            return BackupTransport.this.getCurrentRestoreSet();
        }

        @Override
        public int startRestore(long token, PackageInfo[] packages) throws RemoteException {
            return BackupTransport.this.startRestore(token, packages);
        }

        @Override
        public String nextRestorePackage() throws RemoteException {
            return BackupTransport.this.nextRestorePackage();
        }

        @Override
        public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException {
            return BackupTransport.this.getRestoreData(outFd);
        }

        @Override
        public void finishRestore() throws RemoteException {
            BackupTransport.this.finishRestore();
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ interface IBackupTransport {
    /**
     * Get the data for the application returned by {@link #nextRestorePackage}.
     * @param data An open, writable file into which the backup data should be stored.
     * @return the same error codes as {@link #nextRestorePackage}.
     * @return the same error codes as {@link #startRestore}.
     */
    int getRestoreData(in ParcelFileDescriptor outFd);

+3 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.backup;

import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupTransport;
import android.app.backup.RestoreSet;
import android.content.ComponentName;
import android.content.Context;
@@ -47,7 +48,7 @@ import static android.system.OsConstants.*;
 * later restoring from there.  For testing only.
 */

public class LocalTransport extends IBackupTransport.Stub {
public class LocalTransport extends BackupTransport {
    private static final String TAG = "LocalTransport";
    private static final boolean DEBUG = true;

@@ -217,7 +218,7 @@ public class LocalTransport extends IBackupTransport.Stub {

    // Restore handling
    static final long[] POSSIBLE_SETS = { 2, 3, 4, 5, 6, 7, 8, 9 }; 
    public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
    public RestoreSet[] getAvailableRestoreSets() {
        long[] existing = new long[POSSIBLE_SETS.length + 1];
        int num = 0;

+1 −1
Original line number Diff line number Diff line
@@ -32,6 +32,6 @@ public class LocalTransportService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return sTransport;
        return sTransport.getBinder();
    }
}