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 
17 package android.app.backup;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 import android.content.Context;
21 import android.os.ParcelFileDescriptor;
22 import android.util.Log;
23 
24 import java.io.File;
25 import java.io.FileDescriptor;
26 
27 /**
28  * Base class for the {@link android.app.backup.FileBackupHelper} implementation.
29  */
30 class FileBackupHelperBase {
31     private static final String TAG = "FileBackupHelperBase";
32 
33     long mPtr;
34     Context mContext;
35     boolean mExceptionLogged;
36 
FileBackupHelperBase(Context context)37     FileBackupHelperBase(Context context) {
38         mPtr = ctor();
39         mContext = context;
40     }
41 
finalize()42     protected void finalize() throws Throwable {
43         try {
44             dtor(mPtr);
45         } finally {
46             super.finalize();
47         }
48     }
49 
50     /**
51      * Check the parameters so the native code doesn't have to throw all the exceptions
52      * since it's easier to do that from Java.
53      */
performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState, String[] files, String[] keys)54     static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
55             ParcelFileDescriptor newState, String[] files, String[] keys) {
56         if (files.length == 0) {
57             return;
58         }
59         // files must be all absolute paths
60         for (String f: files) {
61             if (f.charAt(0) != '/') {
62                 throw new RuntimeException("files must have all absolute paths: " + f);
63             }
64         }
65         // the length of files and keys must be the same
66         if (files.length != keys.length) {
67             throw new RuntimeException("files.length=" + files.length
68                     + " keys.length=" + keys.length);
69         }
70         // oldStateFd can be null
71         FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
72         FileDescriptor newStateFd = newState.getFileDescriptor();
73         if (newStateFd == null) {
74             throw new NullPointerException();
75         }
76 
77         int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
78 
79         if (err != 0) {
80             // TODO: more here
81             throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
82         }
83     }
84 
writeFile(File f, BackupDataInputStream in)85     boolean writeFile(File f, BackupDataInputStream in) {
86         int result = -1;
87 
88         // Create the enclosing directory.
89         File parent = f.getParentFile();
90         parent.mkdirs();
91 
92         result = writeFile_native(mPtr, f.getAbsolutePath(), in.mData.mBackupReader);
93         if (result != 0) {
94             // Bail on this entity.  Only log one failure per helper object.
95             if (!mExceptionLogged) {
96                 Log.e(TAG, "Failed restoring file '" + f + "' for app '"
97                         + mContext.getPackageName() + "\' result=0x"
98                         + Integer.toHexString(result));
99                 mExceptionLogged = true;
100             }
101         }
102         return (result == 0);
103     }
104 
105     @UnsupportedAppUsage
writeNewStateDescription(ParcelFileDescriptor fd)106     public void writeNewStateDescription(ParcelFileDescriptor fd) {
107         int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
108         // TODO: Do something with the error.
109     }
110 
isKeyInList(String key, String[] list)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 
ctor()120     private static native long ctor();
dtor(long ptr)121     private static native void dtor(long ptr);
122 
performBackup_native(FileDescriptor oldState, long data, FileDescriptor newState, String[] files, String[] keys)123     native private static int performBackup_native(FileDescriptor oldState,
124             long data, FileDescriptor newState, String[] files, String[] keys);
writeFile_native(long ptr, String filename, long backupReader)125     private static native int writeFile_native(long ptr, String filename, long backupReader);
writeSnapshot_native(long ptr, FileDescriptor fd)126     private static native int writeSnapshot_native(long ptr, FileDescriptor fd);
127 }
128 
129 
130