LocalTransport.java revision 9bbc21a773cbdfbef2876a75c32bda5839647751
1package com.android.internal.backup;
2
3import android.backup.RestoreSet;
4import android.content.Context;
5import android.content.pm.PackageInfo;
6import android.content.pm.PackageManager;
7import android.content.pm.PackageManager.NameNotFoundException;
8import android.os.Environment;
9import android.os.ParcelFileDescriptor;
10import android.os.RemoteException;
11import android.util.Log;
12
13import java.io.File;
14import java.io.FileFilter;
15import java.io.FileInputStream;
16import java.io.FileOutputStream;
17import java.io.IOException;
18import java.util.ArrayList;
19
20/**
21 * Backup transport for stashing stuff into a known location on disk, and
22 * later restoring from there.  For testing only.
23 */
24
25public class LocalTransport extends IBackupTransport.Stub {
26    private static final String TAG = "LocalTransport";
27    private static final String DATA_FILE_NAME = "data";
28
29    private Context mContext;
30    private PackageManager mPackageManager;
31    private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
32    private FileFilter mDirFileFilter = new FileFilter() {
33        public boolean accept(File f) {
34            return f.isDirectory();
35        }
36    };
37
38
39    public LocalTransport(Context context) {
40        mContext = context;
41        mPackageManager = context.getPackageManager();
42    }
43
44    public long requestBackupTime() throws RemoteException {
45        // any time is a good time for local backup
46        return 0;
47    }
48
49    public int startSession() throws RemoteException {
50        return 0;
51    }
52
53    public int endSession() throws RemoteException {
54        return 0;
55    }
56
57    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
58            throws RemoteException {
59        File packageDir = new File(mDataDir, packageInfo.packageName);
60        File imageFileName = new File(packageDir, DATA_FILE_NAME);
61
62        //!!! TODO: process the (partial) update into the persistent restore set:
63
64        // Parse out the existing image file into the key/value map
65
66        // Parse out the backup data into the key/value updates
67
68        // Apply the backup key/value updates to the image
69
70        // Write out the image in the canonical format
71
72        return -1;
73    }
74
75    // Restore handling
76    public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
77        // one hardcoded restore set
78        RestoreSet[] set = new RestoreSet[1];
79        set[0].device = "flash";
80        set[0].name = "Local disk image";
81        set[0].token = 0;
82        return set;
83    }
84
85    public PackageInfo[] getAppSet(int token) throws android.os.RemoteException {
86        // the available packages are the extant subdirs of mDatadir
87        File[] packageDirs = mDataDir.listFiles(mDirFileFilter);
88        ArrayList<PackageInfo> packages = new ArrayList<PackageInfo>();
89        for (File dir : packageDirs) {
90            try {
91                PackageInfo pkg = mPackageManager.getPackageInfo(dir.getName(),
92                        PackageManager.GET_SIGNATURES);
93                if (pkg != null) {
94                    packages.add(pkg);
95                }
96            } catch (NameNotFoundException e) {
97                // restore set contains data for a package not installed on the
98                // phone -- just ignore it.
99            }
100        }
101
102        Log.v(TAG, "Built app set of " + packages.size() + " entries:");
103        for (PackageInfo p : packages) {
104            Log.v(TAG, "    + " + p.packageName);
105        }
106
107        PackageInfo[] result = new PackageInfo[packages.size()];
108        return packages.toArray(result);
109    }
110
111    public int getRestoreData(int token, PackageInfo packageInfo, ParcelFileDescriptor output)
112            throws android.os.RemoteException {
113        // we only support one hardcoded restore set
114        if (token != 0) return -1;
115
116        // the data for a given package is at a known location
117        File packageDir = new File(mDataDir, packageInfo.packageName);
118        File imageFile = new File(packageDir, DATA_FILE_NAME);
119
120        // restore is relatively easy: we already maintain the full data set in
121        // the canonical form understandable to the BackupAgent
122        return copyFileToFD(imageFile, output);
123    }
124
125    private int copyFileToFD(File source, ParcelFileDescriptor dest) {
126        try {
127            FileInputStream in = new FileInputStream(source);
128            FileOutputStream out = new FileOutputStream(dest.getFileDescriptor());
129            byte[] buffer = new byte[4096];
130            int bytesRead;
131            while ((bytesRead = in.read(buffer)) >= 0) {
132                out.write(buffer, 0, bytesRead);
133            }
134        } catch (IOException e) {
135            // something went wrong; claim failure
136            return -1;
137        }
138        return 0;
139    }
140}
141