/*
 * 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 com.android.internal.backup;

import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupTransport;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
import android.util.ArrayMap;
import android.util.Log;

import com.android.org.bouncycastle.util.encoders.Base64;

import libcore.io.IoUtils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;

/**
 * Backup transport for stashing stuff into a known location on disk, and
 * later restoring from there.  For testing only.
 */

public class LocalTransport extends BackupTransport {
    private static final String TAG = "LocalTransport";
    private static final boolean DEBUG = false;

    private static final String TRANSPORT_DIR_NAME
            = "com.android.internal.backup.LocalTransport";

    private static final String TRANSPORT_DESTINATION_STRING
            = "Backing up to debug-only private cache";

    private static final String TRANSPORT_DATA_MANAGEMENT_LABEL
            = "";

    private static final String INCREMENTAL_DIR = "_delta";
    private static final String FULL_DATA_DIR = "_full";

    // The currently-active restore set always has the same (nonzero!) token
    private static final long CURRENT_SET_TOKEN = 1;

    // Size quotas at reasonable values, similar to the current cloud-storage limits
    private static final long FULL_BACKUP_SIZE_QUOTA = 25 * 1024 * 1024;
    private static final long KEY_VALUE_BACKUP_SIZE_QUOTA = 5 * 1024 * 1024;

    private Context mContext;
    private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
    private File mCurrentSetDir = new File(mDataDir, Long.toString(CURRENT_SET_TOKEN));
    private File mCurrentSetIncrementalDir = new File(mCurrentSetDir, INCREMENTAL_DIR);
    private File mCurrentSetFullDir = new File(mCurrentSetDir, FULL_DATA_DIR);

    private PackageInfo[] mRestorePackages = null;
    private int mRestorePackage = -1;  // Index into mRestorePackages
    private int mRestoreType;
    private File mRestoreSetDir;
    private File mRestoreSetIncrementalDir;
    private File mRestoreSetFullDir;

    // Additional bookkeeping for full backup
    private String mFullTargetPackage;
    private ParcelFileDescriptor mSocket;
    private FileInputStream mSocketInputStream;
    private BufferedOutputStream mFullBackupOutputStream;
    private byte[] mFullBackupBuffer;
    private long mFullBackupSize;

    private FileInputStream mCurFullRestoreStream;
    private FileOutputStream mFullRestoreSocketStream;
    private byte[] mFullRestoreBuffer;
    private final LocalTransportParameters mParameters;

    private void makeDataDirs() {
        mCurrentSetDir.mkdirs();
        mCurrentSetFullDir.mkdir();
        mCurrentSetIncrementalDir.mkdir();
    }

    public LocalTransport(Context context, LocalTransportParameters parameters) {
        mContext = context;
        mParameters = parameters;
        makeDataDirs();
    }

    LocalTransportParameters getParameters() {
        return mParameters;
    }

    @Override
    public String name() {
        return new ComponentName(mContext, this.getClass()).flattenToShortString();
    }

    @Override
    public Intent configurationIntent() {
        // The local transport is not user-configurable
        return null;
    }

    @Override
    public String currentDestinationString() {
        return TRANSPORT_DESTINATION_STRING;
    }

    public Intent dataManagementIntent() {
        // The local transport does not present a data-management UI
        // TODO: consider adding simple UI to wipe the archives entirely,
        // for cleaning up the cache partition.
        return null;
    }

    public String dataManagementLabel() {
        return TRANSPORT_DATA_MANAGEMENT_LABEL;
    }

    @Override
    public String transportDirName() {
        return TRANSPORT_DIR_NAME;
    }

    @Override
    public int getTransportFlags() {
        int flags = super.getTransportFlags();
        // Testing for a fake flag and having it set as a boolean in settings prevents anyone from
        // using this it to pull data from the agent
        if (mParameters.isFakeEncryptionFlag()) {
            flags |= BackupAgent.FLAG_FAKE_CLIENT_SIDE_ENCRYPTION_ENABLED;
        }
        return flags;
    }

    @Override
    public long requestBackupTime() {
        // any time is a good time for local backup
        return 0;
    }

    @Override
    public int initializeDevice() {
        if (DEBUG) Log.v(TAG, "wiping all data");
        deleteContents(mCurrentSetDir);
        makeDataDirs();
        return TRANSPORT_OK;
    }

    // Encapsulation of a single k/v element change
    private class KVOperation {
        final String key;     // Element filename, not the raw key, for efficiency
        final byte[] value;   // null when this is a deletion operation

        KVOperation(String k, byte[] v) {
            key = k;
            value = v;
        }
    }

    @Override
    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) {
        if (DEBUG) {
            try {
            StructStat ss = Os.fstat(data.getFileDescriptor());
            Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName
                    + " size=" + ss.st_size);
            } catch (ErrnoException e) {
                Log.w(TAG, "Unable to stat input file in performBackup() on "
                        + packageInfo.packageName);
            }
        }

        File packageDir = new File(mCurrentSetIncrementalDir, packageInfo.packageName);
        packageDir.mkdirs();

        // Each 'record' in the restore set is kept in its own file, named by
        // the record key.  Wind through the data file, extracting individual
        // record operations and building a list of all the updates to apply
        // in this update.
        final ArrayList<KVOperation> changeOps;
        try {
            changeOps = parseBackupStream(data);
        } catch (IOException e) {
            // oops, something went wrong.  abort the operation and return error.
            Log.v(TAG, "Exception reading backup input", e);
            return TRANSPORT_ERROR;
        }

        // Okay, now we've parsed out the delta's individual operations.  We need to measure
        // the effect against what we already have in the datastore to detect quota overrun.
        // So, we first need to tally up the current in-datastore size per key.
        final ArrayMap<String, Integer> datastore = new ArrayMap<>();
        int totalSize = parseKeySizes(packageDir, datastore);

        // ... and now figure out the datastore size that will result from applying the
        // sequence of delta operations
        if (DEBUG) {
            if (changeOps.size() > 0) {
                Log.v(TAG, "Calculating delta size impact");
            } else {
                Log.v(TAG, "No operations in backup stream, so no size change");
            }
        }
        int updatedSize = totalSize;
        for (KVOperation op : changeOps) {
            // Deduct the size of the key we're about to replace, if any
            final Integer curSize = datastore.get(op.key);
            if (curSize != null) {
                updatedSize -= curSize.intValue();
                if (DEBUG && op.value == null) {
                    Log.v(TAG, "  delete " + op.key + ", updated total " + updatedSize);
                }
            }

            // And add back the size of the value we're about to store, if any
            if (op.value != null) {
                updatedSize += op.value.length;
                if (DEBUG) {
                    Log.v(TAG, ((curSize == null) ? "  new " : "  replace ")
                            +  op.key + ", updated total " + updatedSize);
                }
            }
        }

        // If our final size is over quota, report the failure
        if (updatedSize > KEY_VALUE_BACKUP_SIZE_QUOTA) {
            if (DEBUG) {
                Log.i(TAG, "New datastore size " + updatedSize
                        + " exceeds quota " + KEY_VALUE_BACKUP_SIZE_QUOTA);
            }
            return TRANSPORT_QUOTA_EXCEEDED;
        }

        // No problem with storage size, so go ahead and apply the delta operations
        // (in the order that the app provided them)
        for (KVOperation op : changeOps) {
            File element = new File(packageDir, op.key);

            // this is either a deletion or a rewrite-from-zero, so we can just remove
            // the existing file and proceed in either case.
            element.delete();

            // if this wasn't a deletion, put the new data in place
            if (op.value != null) {
                try (FileOutputStream out = new FileOutputStream(element)) {
                    out.write(op.value, 0, op.value.length);
                } catch (IOException e) {
                    Log.e(TAG, "Unable to update key file " + element);
                    return TRANSPORT_ERROR;
                }
            }
        }
        return TRANSPORT_OK;
    }

    // Parses a backup stream into individual key/value operations
    private ArrayList<KVOperation> parseBackupStream(ParcelFileDescriptor data)
            throws IOException {
        ArrayList<KVOperation> changeOps = new ArrayList<>();
        BackupDataInput changeSet = new BackupDataInput(data.getFileDescriptor());
        while (changeSet.readNextHeader()) {
            String key = changeSet.getKey();
            String base64Key = new String(Base64.encode(key.getBytes()));
            int dataSize = changeSet.getDataSize();
            if (DEBUG) {
                Log.v(TAG, "  Delta operation key " + key + "   size " + dataSize
                        + "   key64 " + base64Key);
            }

            byte[] buf = (dataSize >= 0) ? new byte[dataSize] : null;
            if (dataSize >= 0) {
                changeSet.readEntityData(buf, 0, dataSize);
            }
            changeOps.add(new KVOperation(base64Key, buf));
        }
        return changeOps;
    }

    // Reads the given datastore directory, building a table of the value size of each
    // keyed element, and returning the summed total.
    private int parseKeySizes(File packageDir, ArrayMap<String, Integer> datastore) {
        int totalSize = 0;
        final String[] elements = packageDir.list();
        if (elements != null) {
            if (DEBUG) {
                Log.v(TAG, "Existing datastore contents:");
            }
            for (String file : elements) {
                File element = new File(packageDir, file);
                String key = file;  // filename
                int size = (int) element.length();
                totalSize += size;
                if (DEBUG) {
                    Log.v(TAG, "  key " + key + "   size " + size);
                }
                datastore.put(key, size);
            }
            if (DEBUG) {
                Log.v(TAG, "  TOTAL: " + totalSize);
            }
        } else {
            if (DEBUG) {
                Log.v(TAG, "No existing data for this package");
            }
        }
        return totalSize;
    }

    // Deletes the contents but not the given directory
    private void deleteContents(File dirname) {
        File[] contents = dirname.listFiles();
        if (contents != null) {
            for (File f : contents) {
                if (f.isDirectory()) {
                    // delete the directory's contents then fall through
                    // and delete the directory itself.
                    deleteContents(f);
                }
                f.delete();
            }
        }
    }

    @Override
    public int clearBackupData(PackageInfo packageInfo) {
        if (DEBUG) Log.v(TAG, "clearBackupData() pkg=" + packageInfo.packageName);

        File packageDir = new File(mCurrentSetIncrementalDir, packageInfo.packageName);
        final File[] fileset = packageDir.listFiles();
        if (fileset != null) {
            for (File f : fileset) {
                f.delete();
            }
            packageDir.delete();
        }

        packageDir = new File(mCurrentSetFullDir, packageInfo.packageName);
        final File[] tarballs = packageDir.listFiles();
        if (tarballs != null) {
            for (File f : tarballs) {
                f.delete();
            }
            packageDir.delete();
        }

        return TRANSPORT_OK;
    }

    @Override
    public int finishBackup() {
        if (DEBUG) Log.v(TAG, "finishBackup() of " + mFullTargetPackage);
        return tearDownFullBackup();
    }

    // ------------------------------------------------------------------------------------
    // Full backup handling

    private int tearDownFullBackup() {
        if (mSocket != null) {
            try {
                if (mFullBackupOutputStream != null) {
                    mFullBackupOutputStream.flush();
                    mFullBackupOutputStream.close();
                }
                mSocketInputStream = null;
                mFullTargetPackage = null;
                mSocket.close();
            } catch (IOException e) {
                if (DEBUG) {
                    Log.w(TAG, "Exception caught in tearDownFullBackup()", e);
                }
                return TRANSPORT_ERROR;
            } finally {
                mSocket = null;
                mFullBackupOutputStream = null;
            }
        }
        return TRANSPORT_OK;
    }

    private File tarballFile(String pkgName) {
        return new File(mCurrentSetFullDir, pkgName);
    }

    @Override
    public long requestFullBackupTime() {
        return 0;
    }

    @Override
    public int checkFullBackupSize(long size) {
        int result = TRANSPORT_OK;
        // Decline zero-size "backups"
        if (size <= 0) {
            result = TRANSPORT_PACKAGE_REJECTED;
        } else if (size > FULL_BACKUP_SIZE_QUOTA) {
            result = TRANSPORT_QUOTA_EXCEEDED;
        }
        if (result != TRANSPORT_OK) {
            if (DEBUG) {
                Log.v(TAG, "Declining backup of size " + size);
            }
        }
        return result;
    }

    @Override
    public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) {
        if (mSocket != null) {
            Log.e(TAG, "Attempt to initiate full backup while one is in progress");
            return TRANSPORT_ERROR;
        }

        if (DEBUG) {
            Log.i(TAG, "performFullBackup : " + targetPackage);
        }

        // We know a priori that we run in the system process, so we need to make
        // sure to dup() our own copy of the socket fd.  Transports which run in
        // their own processes must not do this.
        try {
            mFullBackupSize = 0;
            mSocket = ParcelFileDescriptor.dup(socket.getFileDescriptor());
            mSocketInputStream = new FileInputStream(mSocket.getFileDescriptor());
        } catch (IOException e) {
            Log.e(TAG, "Unable to process socket for full backup");
            return TRANSPORT_ERROR;
        }

        mFullTargetPackage = targetPackage.packageName;
        mFullBackupBuffer = new byte[4096];

        return TRANSPORT_OK;
    }

    @Override
    public int sendBackupData(final int numBytes) {
        if (mSocket == null) {
            Log.w(TAG, "Attempted sendBackupData before performFullBackup");
            return TRANSPORT_ERROR;
        }

        mFullBackupSize += numBytes;
        if (mFullBackupSize > FULL_BACKUP_SIZE_QUOTA) {
            return TRANSPORT_QUOTA_EXCEEDED;
        }

        if (numBytes > mFullBackupBuffer.length) {
            mFullBackupBuffer = new byte[numBytes];
        }

        if (mFullBackupOutputStream == null) {
            FileOutputStream tarstream;
            try {
                File tarball = tarballFile(mFullTargetPackage);
                tarstream = new FileOutputStream(tarball);
            } catch (FileNotFoundException e) {
                return TRANSPORT_ERROR;
            }
            mFullBackupOutputStream = new BufferedOutputStream(tarstream);
        }

        int bytesLeft = numBytes;
        while (bytesLeft > 0) {
            try {
            int nRead = mSocketInputStream.read(mFullBackupBuffer, 0, bytesLeft);
            if (nRead < 0) {
                // Something went wrong if we expect data but saw EOD
                Log.w(TAG, "Unexpected EOD; failing backup");
                return TRANSPORT_ERROR;
            }
            mFullBackupOutputStream.write(mFullBackupBuffer, 0, nRead);
            bytesLeft -= nRead;
            } catch (IOException e) {
                Log.e(TAG, "Error handling backup data for " + mFullTargetPackage);
                return TRANSPORT_ERROR;
            }
        }
        if (DEBUG) {
            Log.v(TAG, "   stored " + numBytes + " of data");
        }
        return TRANSPORT_OK;
    }

    // For now we can't roll back, so just tear everything down.
    @Override
    public void cancelFullBackup() {
        if (DEBUG) {
            Log.i(TAG, "Canceling full backup of " + mFullTargetPackage);
        }
        File archive = tarballFile(mFullTargetPackage);
        tearDownFullBackup();
        if (archive.exists()) {
            archive.delete();
        }
    }

    // ------------------------------------------------------------------------------------
    // Restore handling
    static final long[] POSSIBLE_SETS = { 2, 3, 4, 5, 6, 7, 8, 9 };

    @Override
    public RestoreSet[] getAvailableRestoreSets() {
        long[] existing = new long[POSSIBLE_SETS.length + 1];
        int num = 0;

        // see which possible non-current sets exist...
        for (long token : POSSIBLE_SETS) {
            if ((new File(mDataDir, Long.toString(token))).exists()) {
                existing[num++] = token;
            }
        }
        // ...and always the currently-active set last
        existing[num++] = CURRENT_SET_TOKEN;

        RestoreSet[] available = new RestoreSet[num];
        for (int i = 0; i < available.length; i++) {
            available[i] = new RestoreSet("Local disk image", "flash", existing[i]);
        }
        return available;
    }

    @Override
    public long getCurrentRestoreSet() {
        // The current restore set always has the same token
        return CURRENT_SET_TOKEN;
    }

    @Override
    public int startRestore(long token, PackageInfo[] packages) {
        if (DEBUG) Log.v(TAG, "start restore " + token + " : " + packages.length
                + " matching packages");
        mRestorePackages = packages;
        mRestorePackage = -1;
        mRestoreSetDir = new File(mDataDir, Long.toString(token));
        mRestoreSetIncrementalDir = new File(mRestoreSetDir, INCREMENTAL_DIR);
        mRestoreSetFullDir = new File(mRestoreSetDir, FULL_DATA_DIR);
        return TRANSPORT_OK;
    }

    @Override
    public RestoreDescription nextRestorePackage() {
        if (DEBUG) {
            Log.v(TAG, "nextRestorePackage() : mRestorePackage=" + mRestorePackage
                    + " length=" + mRestorePackages.length);
        }
        if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");

        boolean found = false;
        while (++mRestorePackage < mRestorePackages.length) {
            String name = mRestorePackages[mRestorePackage].packageName;

            // If we have key/value data for this package, deliver that
            // skip packages where we have a data dir but no actual contents
            String[] contents = (new File(mRestoreSetIncrementalDir, name)).list();
            if (contents != null && contents.length > 0) {
                if (DEBUG) {
                    Log.v(TAG, "  nextRestorePackage(TYPE_KEY_VALUE) @ "
                        + mRestorePackage + " = " + name);
                }
                mRestoreType = RestoreDescription.TYPE_KEY_VALUE;
                found = true;
            }

            if (!found) {
                // No key/value data; check for [non-empty] full data
                File maybeFullData = new File(mRestoreSetFullDir, name);
                if (maybeFullData.length() > 0) {
                    if (DEBUG) {
                        Log.v(TAG, "  nextRestorePackage(TYPE_FULL_STREAM) @ "
                                + mRestorePackage + " = " + name);
                    }
                    mRestoreType = RestoreDescription.TYPE_FULL_STREAM;
                    mCurFullRestoreStream = null;   // ensure starting from the ground state
                    found = true;
                }
            }

            if (found) {
                return new RestoreDescription(name, mRestoreType);
            }

            if (DEBUG) {
                Log.v(TAG, "  ... package @ " + mRestorePackage + " = " + name
                        + " has no data; skipping");
            }
        }

        if (DEBUG) Log.v(TAG, "  no more packages to restore");
        return RestoreDescription.NO_MORE_PACKAGES;
    }

    @Override
    public int getRestoreData(ParcelFileDescriptor outFd) {
        if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
        if (mRestorePackage < 0) throw new IllegalStateException("nextRestorePackage not called");
        if (mRestoreType != RestoreDescription.TYPE_KEY_VALUE) {
            throw new IllegalStateException("getRestoreData(fd) for non-key/value dataset");
        }
        File packageDir = new File(mRestoreSetIncrementalDir,
                mRestorePackages[mRestorePackage].packageName);

        // The restore set is the concatenation of the individual record blobs,
        // each of which is a file in the package's directory.  We return the
        // data in lexical order sorted by key, so that apps which use synthetic
        // keys like BLOB_1, BLOB_2, etc will see the date in the most obvious
        // order.
        ArrayList<DecodedFilename> blobs = contentsByKey(packageDir);
        if (blobs == null) {  // nextRestorePackage() ensures the dir exists, so this is an error
            Log.e(TAG, "No keys for package: " + packageDir);
            return TRANSPORT_ERROR;
        }

        // We expect at least some data if the directory exists in the first place
        if (DEBUG) Log.v(TAG, "  getRestoreData() found " + blobs.size() + " key files");
        BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
        try {
            for (DecodedFilename keyEntry : blobs) {
                File f = keyEntry.file;
                FileInputStream in = new FileInputStream(f);
                try {
                    int size = (int) f.length();
                    byte[] buf = new byte[size];
                    in.read(buf);
                    if (DEBUG) Log.v(TAG, "    ... key=" + keyEntry.key + " size=" + size);
                    out.writeEntityHeader(keyEntry.key, size);
                    out.writeEntityData(buf, size);
                } finally {
                    in.close();
                }
            }
            return TRANSPORT_OK;
        } catch (IOException e) {
            Log.e(TAG, "Unable to read backup records", e);
            return TRANSPORT_ERROR;
        }
    }

    static class DecodedFilename implements Comparable<DecodedFilename> {
        public File file;
        public String key;

        public DecodedFilename(File f) {
            file = f;
            key = new String(Base64.decode(f.getName()));
        }

        @Override
        public int compareTo(DecodedFilename other) {
            // sorts into ascending lexical order by decoded key
            return key.compareTo(other.key);
        }
    }

    // Return a list of the files in the given directory, sorted lexically by
    // the Base64-decoded file name, not by the on-disk filename
    private ArrayList<DecodedFilename> contentsByKey(File dir) {
        File[] allFiles = dir.listFiles();
        if (allFiles == null || allFiles.length == 0) {
            return null;
        }

        // Decode the filenames into keys then sort lexically by key
        ArrayList<DecodedFilename> contents = new ArrayList<DecodedFilename>();
        for (File f : allFiles) {
            contents.add(new DecodedFilename(f));
        }
        Collections.sort(contents);
        return contents;
    }

    @Override
    public void finishRestore() {
        if (DEBUG) Log.v(TAG, "finishRestore()");
        if (mRestoreType == RestoreDescription.TYPE_FULL_STREAM) {
            resetFullRestoreState();
        }
        mRestoreType = 0;
    }

    // ------------------------------------------------------------------------------------
    // Full restore handling

    private void resetFullRestoreState() {
        IoUtils.closeQuietly(mCurFullRestoreStream);
        mCurFullRestoreStream = null;
        mFullRestoreSocketStream = null;
        mFullRestoreBuffer = null;
    }

    /**
     * Ask the transport to provide data for the "current" package being restored.  The
     * transport then writes some data to the socket supplied to this call, and returns
     * the number of bytes written.  The system will then read that many bytes and
     * stream them to the application's agent for restore, then will call this method again
     * to receive the next chunk of the archive.  This sequence will be repeated until the
     * transport returns zero indicating that all of the package's data has been delivered
     * (or returns a negative value indicating some sort of hard error condition at the
     * transport level).
     *
     * <p>After this method returns zero, the system will then call
     * {@link #getNextFullRestorePackage()} to begin the restore process for the next
     * application, and the sequence begins again.
     *
     * @param socket The file descriptor that the transport will use for delivering the
     *    streamed archive.
     * @return 0 when no more data for the current package is available.  A positive value
     *    indicates the presence of that much data to be delivered to the app.  A negative
     *    return value is treated as equivalent to {@link BackupTransport#TRANSPORT_ERROR},
     *    indicating a fatal error condition that precludes further restore operations
     *    on the current dataset.
     */
    @Override
    public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) {
        if (mRestoreType != RestoreDescription.TYPE_FULL_STREAM) {
            throw new IllegalStateException("Asked for full restore data for non-stream package");
        }

        // first chunk?
        if (mCurFullRestoreStream == null) {
            final String name = mRestorePackages[mRestorePackage].packageName;
            if (DEBUG) Log.i(TAG, "Starting full restore of " + name);
            File dataset = new File(mRestoreSetFullDir, name);
            try {
                mCurFullRestoreStream = new FileInputStream(dataset);
            } catch (IOException e) {
                // If we can't open the target package's tarball, we return the single-package
                // error code and let the caller go on to the next package.
                Log.e(TAG, "Unable to read archive for " + name);
                return TRANSPORT_PACKAGE_REJECTED;
            }
            mFullRestoreSocketStream = new FileOutputStream(socket.getFileDescriptor());
            mFullRestoreBuffer = new byte[2*1024];
        }

        int nRead;
        try {
            nRead = mCurFullRestoreStream.read(mFullRestoreBuffer);
            if (nRead < 0) {
                // EOF: tell the caller we're done
                nRead = NO_MORE_DATA;
            } else if (nRead == 0) {
                // This shouldn't happen when reading a FileInputStream; we should always
                // get either a positive nonzero byte count or -1.  Log the situation and
                // treat it as EOF.
                Log.w(TAG, "read() of archive file returned 0; treating as EOF");
                nRead = NO_MORE_DATA;
            } else {
                if (DEBUG) {
                    Log.i(TAG, "   delivering restore chunk: " + nRead);
                }
                mFullRestoreSocketStream.write(mFullRestoreBuffer, 0, nRead);
            }
        } catch (IOException e) {
            return TRANSPORT_ERROR;  // Hard error accessing the file; shouldn't happen
        } finally {
            // Most transports will need to explicitly close 'socket' here, but this transport
            // is in the same process as the caller so it can leave it up to the backup manager
            // to manage both socket fds.
        }

        return nRead;
    }

    /**
     * If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM}
     * data for restore, it will invoke this method to tell the transport that it should
     * abandon the data download for the current package.  The OS will then either call
     * {@link #nextRestorePackage()} again to move on to restoring the next package in the
     * set being iterated over, or will call {@link #finishRestore()} to shut down the restore
     * operation.
     *
     * @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the
     *    current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious
     *    transport-level failure.  If the transport reports an error here, the entire restore
     *    operation will immediately be finished with no further attempts to restore app data.
     */
    @Override
    public int abortFullRestore() {
        if (mRestoreType != RestoreDescription.TYPE_FULL_STREAM) {
            throw new IllegalStateException("abortFullRestore() but not currently restoring");
        }
        resetFullRestoreState();
        mRestoreType = 0;
        return TRANSPORT_OK;
    }

    @Override
    public long getBackupQuota(String packageName, boolean isFullBackup) {
        return isFullBackup ? FULL_BACKUP_SIZE_QUOTA : KEY_VALUE_BACKUP_SIZE_QUOTA;
    }
}
