summaryrefslogtreecommitdiffstats
path: root/core/jni/android_backup_BackupDataInput.cpp
blob: 90763b0c4561810a7068ab172854f31ba7d0e7f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "FileBackupHelper_native"
#include <utils/Log.h>

#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>

#include <androidfw/BackupHelpers.h>

namespace android
{

// android.app.backup.BackupDataInput$EntityHeader
static jfieldID s_keyField = 0;
static jfieldID s_dataSizeField = 0;

static jlong
ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
{
    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    if (fd == -1) {
        return (jlong)NULL;
    }

    return (jlong)new BackupDataReader(fd);
}

static void
dtor_native(JNIEnv* env, jobject clazz, jlong r)
{
    delete (BackupDataReader*)r;
}

static jint
readNextHeader_native(JNIEnv* env, jobject clazz, jlong r, jobject entity)
{
    int err;
    bool done;
    BackupDataReader* reader = (BackupDataReader*)r;

    int type = 0;

    err = reader->ReadNextHeader(&done, &type);
    if (done) {
        return 1;
    }

    if (err != 0) {
        return err < 0 ? err : -1;
    }

    switch (type) {
    case BACKUP_HEADER_ENTITY_V1:
    {
        String8 key;
        size_t dataSize;
        err = reader->ReadEntityHeader(&key, &dataSize);
        if (err != 0) {
            return err < 0 ? err : -1;
        }
        // TODO: Set the fields in the entity object
        jstring keyStr = env->NewStringUTF(key.string());
        env->SetObjectField(entity, s_keyField, keyStr);
        env->SetIntField(entity, s_dataSizeField, dataSize);
        return 0;
    }
    default:
        ALOGD("Unknown header type: 0x%08x\n", type);
        return -1;
    }

    // done
    return 1;
}

static jint
readEntityData_native(JNIEnv* env, jobject clazz, jlong r, jbyteArray data, jint offset, jint size)
{
    int err;
    BackupDataReader* reader = (BackupDataReader*)r;

    if (env->GetArrayLength(data) < (size+offset)) {
        // size mismatch
        return -1;
    }

    jbyte* dataBytes = env->GetByteArrayElements(data, NULL);
    if (dataBytes == NULL) {
        return -2;
    }

    err = reader->ReadEntityData(dataBytes+offset, size);

    env->ReleaseByteArrayElements(data, dataBytes, 0);

    return err;
}

static jint
skipEntityData_native(JNIEnv* env, jobject clazz, jlong r)
{
    int err;
    BackupDataReader* reader = (BackupDataReader*)r;

    err = reader->SkipEntityData();

    return err;
}

static const JNINativeMethod g_methods[] = {
    { "ctor", "(Ljava/io/FileDescriptor;)J", (void*)ctor_native },
    { "dtor", "(J)V", (void*)dtor_native },
    { "readNextHeader_native", "(JLandroid/app/backup/BackupDataInput$EntityHeader;)I",
            (void*)readNextHeader_native },
    { "readEntityData_native", "(J[BII)I", (void*)readEntityData_native },
    { "skipEntityData_native", "(J)I", (void*)skipEntityData_native },
};

int register_android_backup_BackupDataInput(JNIEnv* env)
{
    //ALOGD("register_android_backup_BackupDataInput");

    jclass clazz = env->FindClass("android/app/backup/BackupDataInput$EntityHeader");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.backup.BackupDataInput.EntityHeader");
    s_keyField = env->GetFieldID(clazz, "key", "Ljava/lang/String;");
    LOG_FATAL_IF(s_keyField == NULL,
            "Unable to find key field in android.app.backup.BackupDataInput.EntityHeader");
    s_dataSizeField = env->GetFieldID(clazz, "dataSize", "I");
    LOG_FATAL_IF(s_dataSizeField == NULL,
            "Unable to find dataSize field in android.app.backup.BackupDataInput.EntityHeader");

    return AndroidRuntime::registerNativeMethods(env, "android/app/backup/BackupDataInput",
            g_methods, NELEM(g_methods));
}

}