106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato/*
206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * Copyright (C) 2009 The Android Open Source Project
306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato *
406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * you may not use this file except in compliance with the License.
606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * You may obtain a copy of the License at
706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato *
806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato *
1006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * Unless required by applicable law or agreed to in writing, software
1106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
1206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * See the License for the specific language governing permissions and
1406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato * limitations under the License.
1506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato */
1606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
174528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tatepackage android.app.backup;
1806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
1906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onoratoimport android.content.Context;
2006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onoratoimport android.os.ParcelFileDescriptor;
2106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onoratoimport android.util.Log;
2206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
2306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onoratoimport java.io.File;
2406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onoratoimport java.io.FileDescriptor;
2506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
265a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root/**
274528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tate * Base class for the {@link android.app.backup.FileBackupHelper} implementation.
285a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root */
2906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onoratoclass FileBackupHelperBase {
305a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root    private static final String TAG = "FileBackupHelperBase";
3106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
3206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    int mPtr;
3306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    Context mContext;
3406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    boolean mExceptionLogged;
3506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
3606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    FileBackupHelperBase(Context context) {
3706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        mPtr = ctor();
3806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        mContext = context;
3906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    }
4006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
4106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    protected void finalize() throws Throwable {
4206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        try {
4306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            dtor(mPtr);
4406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        } finally {
4506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            super.finalize();
4606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
4706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    }
4806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
4906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    /**
505a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * Check the parameters so the native code doesn't have to throw all the exceptions
515a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * since it's easier to do that from Java.
5206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato     */
5306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
5406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            ParcelFileDescriptor newState, String[] files, String[] keys) {
5506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        if (files.length == 0) {
5606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            return;
5706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
5806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        // files must be all absolute paths
5906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        for (String f: files) {
6006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            if (f.charAt(0) != '/') {
6106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato                throw new RuntimeException("files must have all absolute paths: " + f);
6206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            }
6306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
6406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        // the length of files and keys must be the same
6506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        if (files.length != keys.length) {
6606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            throw new RuntimeException("files.length=" + files.length
6706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato                    + " keys.length=" + keys.length);
6806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
6906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        // oldStateFd can be null
7006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
7106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        FileDescriptor newStateFd = newState.getFileDescriptor();
7206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        if (newStateFd == null) {
7306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            throw new NullPointerException();
7406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
7506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
7606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
7706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
7806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        if (err != 0) {
7906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            // TODO: more here
8006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
8106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
8206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    }
8306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
843f64f8d8fc05189777e83b4efd3882cbc661fdebChristopher Tate    boolean writeFile(File f, BackupDataInputStream in) {
8506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        int result = -1;
8606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
8706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        // Create the enclosing directory.
8806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        File parent = f.getParentFile();
8906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        parent.mkdirs();
9006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
91e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate        result = writeFile_native(mPtr, f.getAbsolutePath(), in.mData.mBackupReader);
9206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        if (result != 0) {
9306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            // Bail on this entity.  Only log one failure per helper object.
9406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            if (!mExceptionLogged) {
9506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato                Log.e(TAG, "Failed restoring file '" + f + "' for app '"
9606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato                        + mContext.getPackageName() + "\' result=0x"
9706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato                        + Integer.toHexString(result));
9806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato                mExceptionLogged = true;
9906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            }
10006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
1013f64f8d8fc05189777e83b4efd3882cbc661fdebChristopher Tate        return (result == 0);
10206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    }
10306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
104e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate    public void writeNewStateDescription(ParcelFileDescriptor fd) {
10506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
10606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        // TODO: Do something with the error.
10706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    }
10806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
10906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    boolean isKeyInList(String key, String[] list) {
11006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        for (String s: list) {
11106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            if (s.equals(key)) {
11206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato                return true;
11306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            }
11406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        }
11506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        return false;
11606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    }
11706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
11806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    private static native int ctor();
11906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    private static native void dtor(int ptr);
12006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
12106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    native private static int performBackup_native(FileDescriptor oldState,
12206290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato            int data, FileDescriptor newState, String[] files, String[] keys);
12306290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
12406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    private static native int writeFile_native(int ptr, String filename, int backupReader);
12506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
12606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato}
12706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
12806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
129