1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.backup;
18
19import android.content.Context;
20import android.os.ParcelFileDescriptor;
21import android.util.Log;
22
23import java.io.InputStream;
24import java.io.File;
25import java.io.FileDescriptor;
26import java.io.FileOutputStream;
27
28class FileBackupHelperBase {
29    private static final String TAG = "RestoreHelperBase";
30
31    int mPtr;
32    Context mContext;
33    boolean mExceptionLogged;
34
35    FileBackupHelperBase(Context context) {
36        mPtr = ctor();
37        mContext = context;
38    }
39
40    protected void finalize() throws Throwable {
41        try {
42            dtor(mPtr);
43        } finally {
44            super.finalize();
45        }
46    }
47
48    /**
49     * Check the parameters so the native code doens't have to throw all the exceptions
50     * since it's easier to do that from java.
51     */
52    static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
53            ParcelFileDescriptor newState, String[] files, String[] keys) {
54        if (files.length == 0) {
55            return;
56        }
57        // files must be all absolute paths
58        for (String f: files) {
59            if (f.charAt(0) != '/') {
60                throw new RuntimeException("files must have all absolute paths: " + f);
61            }
62        }
63        // the length of files and keys must be the same
64        if (files.length != keys.length) {
65            throw new RuntimeException("files.length=" + files.length
66                    + " keys.length=" + keys.length);
67        }
68        // oldStateFd can be null
69        FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
70        FileDescriptor newStateFd = newState.getFileDescriptor();
71        if (newStateFd == null) {
72            throw new NullPointerException();
73        }
74
75        int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
76
77        if (err != 0) {
78            // TODO: more here
79            throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
80        }
81    }
82
83    void writeFile(File f, InputStream in) {
84        if (!(in instanceof BackupDataInputStream)) {
85            throw new IllegalStateException("input stream must be a BackupDataInputStream");
86        }
87        int result = -1;
88
89        // Create the enclosing directory.
90        File parent = f.getParentFile();
91        parent.mkdirs();
92
93        result = writeFile_native(mPtr, f.getAbsolutePath(),
94                ((BackupDataInputStream)in).mData.mBackupReader);
95        if (result != 0) {
96            // Bail on this entity.  Only log one failure per helper object.
97            if (!mExceptionLogged) {
98                Log.e(TAG, "Failed restoring file '" + f + "' for app '"
99                        + mContext.getPackageName() + "\' result=0x"
100                        + Integer.toHexString(result));
101                mExceptionLogged = true;
102            }
103        }
104    }
105
106    public void writeRestoreSnapshot(ParcelFileDescriptor fd) {
107        int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
108        // TODO: Do something with the error.
109    }
110
111    boolean isKeyInList(String key, String[] list) {
112        for (String s: list) {
113            if (s.equals(key)) {
114                return true;
115            }
116        }
117        return false;
118    }
119
120    private static native int ctor();
121    private static native void dtor(int ptr);
122
123    native private static int performBackup_native(FileDescriptor oldState,
124            int data, FileDescriptor newState, String[] files, String[] keys);
125
126    private static native int writeFile_native(int ptr, String filename, int backupReader);
127    private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
128}
129
130
131