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 #define LOG_TAG "FileBackupHelper_native"
18 #include <utils/Log.h>
19 
20 #include <nativehelper/JNIHelp.h>
21 #include <android_runtime/AndroidRuntime.h>
22 
23 #include <androidfw/BackupHelpers.h>
24 
25 #include "core_jni_helpers.h"
26 
27 namespace android
28 {
29 
30 // android.app.backup.BackupDataInput$EntityHeader
31 static jfieldID s_keyField = 0;
32 static jfieldID s_dataSizeField = 0;
33 
34 static jlong
ctor_native(JNIEnv * env,jobject clazz,jobject fileDescriptor)35 ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
36 {
37     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
38     if (fd == -1) {
39         return (jlong)NULL;
40     }
41 
42     return (jlong)new BackupDataReader(fd);
43 }
44 
45 static void
dtor_native(JNIEnv * env,jobject clazz,jlong r)46 dtor_native(JNIEnv* env, jobject clazz, jlong r)
47 {
48     delete (BackupDataReader*)r;
49 }
50 
51 static jint
readNextHeader_native(JNIEnv * env,jobject clazz,jlong r,jobject entity)52 readNextHeader_native(JNIEnv* env, jobject clazz, jlong r, jobject entity)
53 {
54     int err;
55     bool done;
56     BackupDataReader* reader = (BackupDataReader*)r;
57 
58     int type = 0;
59 
60     err = reader->ReadNextHeader(&done, &type);
61     if (done) {
62         return 1;
63     }
64 
65     if (err != 0) {
66         return err < 0 ? err : -1;
67     }
68 
69     switch (type) {
70     case BACKUP_HEADER_ENTITY_V1:
71     {
72         String8 key;
73         size_t dataSize;
74         err = reader->ReadEntityHeader(&key, &dataSize);
75         if (err != 0) {
76             return err < 0 ? err : -1;
77         }
78         // TODO: Set the fields in the entity object
79         jstring keyStr = env->NewStringUTF(key.string());
80         env->SetObjectField(entity, s_keyField, keyStr);
81         env->SetIntField(entity, s_dataSizeField, dataSize);
82         return 0;
83     }
84     default:
85         ALOGD("Unknown header type: 0x%08x\n", type);
86         return -1;
87     }
88 
89     // done
90     return 1;
91 }
92 
93 static jint
readEntityData_native(JNIEnv * env,jobject clazz,jlong r,jbyteArray data,jint offset,jint size)94 readEntityData_native(JNIEnv* env, jobject clazz, jlong r, jbyteArray data, jint offset, jint size)
95 {
96     int err;
97     BackupDataReader* reader = (BackupDataReader*)r;
98 
99     if (env->GetArrayLength(data) < (size+offset)) {
100         // size mismatch
101         return -1;
102     }
103 
104     jbyte* dataBytes = env->GetByteArrayElements(data, NULL);
105     if (dataBytes == NULL) {
106         return -2;
107     }
108 
109     err = reader->ReadEntityData(dataBytes+offset, size);
110 
111     env->ReleaseByteArrayElements(data, dataBytes, 0);
112 
113     return err;
114 }
115 
116 static jint
skipEntityData_native(JNIEnv * env,jobject clazz,jlong r)117 skipEntityData_native(JNIEnv* env, jobject clazz, jlong r)
118 {
119     int err;
120     BackupDataReader* reader = (BackupDataReader*)r;
121 
122     err = reader->SkipEntityData();
123 
124     return err;
125 }
126 
127 static const JNINativeMethod g_methods[] = {
128     { "ctor", "(Ljava/io/FileDescriptor;)J", (void*)ctor_native },
129     { "dtor", "(J)V", (void*)dtor_native },
130     { "readNextHeader_native", "(JLandroid/app/backup/BackupDataInput$EntityHeader;)I",
131             (void*)readNextHeader_native },
132     { "readEntityData_native", "(J[BII)I", (void*)readEntityData_native },
133     { "skipEntityData_native", "(J)I", (void*)skipEntityData_native },
134 };
135 
register_android_backup_BackupDataInput(JNIEnv * env)136 int register_android_backup_BackupDataInput(JNIEnv* env)
137 {
138     //ALOGD("register_android_backup_BackupDataInput");
139 
140     jclass clazz = FindClassOrDie(env, "android/app/backup/BackupDataInput$EntityHeader");
141     s_keyField = GetFieldIDOrDie(env, clazz, "key", "Ljava/lang/String;");
142     s_dataSizeField = GetFieldIDOrDie(env, clazz, "dataSize", "I");
143 
144     return RegisterMethodsOrDie(env, "android/app/backup/BackupDataInput", g_methods,
145                                 NELEM(g_methods));
146 }
147 
148 }
149