summaryrefslogtreecommitdiff
path: root/jni
diff options
context:
space:
mode:
author Dipankar Bhardwaj <dipankarb@google.com> 2024-04-03 12:58:05 +0000
committer Dipankar Bhardwaj <dipankarb@google.com> 2024-05-10 12:12:31 +0000
commit16b87803e0b0ecab9434a37fbfd12da36d5d8d16 (patch)
treea64796b397158fae364831aaa9ec689e552a0ece /jni
parenta81809af62af64f12a8120057aa59177d22717e7 (diff)
Create leveldb manager code
Added jni code to perform leveldb operations. Test is executed in fake mediaprovider and leveldb library is loaded for the same. Test: atest com.android.providers.media.leveldb.LevelDBProxyTest Bug: 336793168 Change-Id: Ib9821430d7494118ab3328efc317cb7f33082491
Diffstat (limited to 'jni')
-rw-r--r--jni/Android.bp81
-rw-r--r--jni/com_android_providers_media_leveldb_LevelDBInstance.cpp168
2 files changed, 238 insertions, 11 deletions
diff --git a/jni/Android.bp b/jni/Android.bp
index 35721d5a6..44832efcc 100644
--- a/jni/Android.bp
+++ b/jni/Android.bp
@@ -30,7 +30,7 @@ cc_library_shared {
"MediaProviderWrapper.cpp",
"ReaddirHelper.cpp",
"RedactionInfo.cpp",
- "node.cpp"
+ "node.cpp",
],
header_libs: [
@@ -44,7 +44,7 @@ cc_library_shared {
"leveldb",
"liblog",
"libfuse",
- "libandroid"
+ "libandroid",
],
static_libs: [
@@ -73,15 +73,60 @@ cc_library_shared {
min_sdk_version: "30",
}
+cc_library_shared {
+ name: "libleveldb_jni",
+
+ srcs: [
+ "com_android_providers_media_leveldb_LevelDBInstance.cpp",
+ ],
+
+ header_libs: [
+ "libnativehelper_header_only",
+ ],
+
+ apex_available: ["com.android.mediaprovider"],
+
+ shared_libs: [
+ "leveldb",
+ "liblog",
+ "libandroid",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
+ "-Wthread-safety",
+ ],
+
+ tidy: true,
+ tidy_checks: [
+ "-google-runtime-int",
+ "-performance-no-int-to-ptr",
+ ],
+
+ sdk_version: "current",
+ stl: "c++_static",
+ min_sdk_version: "30",
+}
+
cc_test {
name: "fuse_node_test",
- test_suites: ["device-tests", "mts-mediaprovider"],
+ test_suites: [
+ "device-tests",
+ "mts-mediaprovider",
+ ],
test_config: "fuse_node_test.xml",
compile_multilib: "both",
multilib: {
- lib32: { suffix: "32", },
- lib64: { suffix: "64", },
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
},
srcs: [
@@ -112,13 +157,20 @@ cc_test {
cc_test {
name: "RedactionInfoTest",
- test_suites: ["device-tests", "mts-mediaprovider"],
+ test_suites: [
+ "device-tests",
+ "mts-mediaprovider",
+ ],
test_config: "RedactionInfoTest.xml",
compile_multilib: "both",
multilib: {
- lib32: { suffix: "32", },
- lib64: { suffix: "64", },
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
},
srcs: [
@@ -144,13 +196,20 @@ cc_test {
cc_test {
name: "FuseUtilsTest",
- test_suites: ["device-tests", "mts-mediaprovider"],
+ test_suites: [
+ "device-tests",
+ "mts-mediaprovider",
+ ],
test_config: "FuseUtilsTest.xml",
compile_multilib: "both",
multilib: {
- lib32: { suffix: "32", },
- lib64: { suffix: "64", },
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
},
srcs: [
diff --git a/jni/com_android_providers_media_leveldb_LevelDBInstance.cpp b/jni/com_android_providers_media_leveldb_LevelDBInstance.cpp
new file mode 100644
index 000000000..8b40dd6ff
--- /dev/null
+++ b/jni/com_android_providers_media_leveldb_LevelDBInstance.cpp
@@ -0,0 +1,168 @@
+#include <jni.h>
+#include <nativehelper/scoped_utf_chars.h>
+
+#include "leveldb/db.h"
+
+#ifndef _Included_com_android_providers_media_leveldb_LevelDBInstance
+#define _Included_com_android_providers_media_leveldb_LevelDBInstance
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_android_providers_media_leveldb_LevelDBInstance_MAX_BULK_INSERT_ENTRIES
+#define com_android_providers_media_leveldb_LevelDBInstance_MAX_BULK_INSERT_ENTRIES 100L
+
+static std::string getStatusCode(leveldb::Status status) {
+ if (status.ok()) {
+ return "0";
+ } else if (status.IsNotFound()) {
+ return "1";
+ } else if (status.IsInvalidArgument()) {
+ return "2";
+ } else {
+ return "3";
+ }
+}
+
+static jobject createLevelDBResult(JNIEnv* env, leveldb::Status status, std::string value) {
+ // Create the object of the class LevelDBResult
+ jclass levelDbResultClass = env->FindClass("com/android/providers/media/leveldb/LevelDBResult");
+ jobject levelDbResultData = env->AllocObject(levelDbResultClass);
+
+ // Get the UserData fields to be set
+ jfieldID codeField = env->GetFieldID(levelDbResultClass, "mCode", "Ljava/lang/String;");
+ jfieldID messageField =
+ env->GetFieldID(levelDbResultClass, "mErrorMessage", "Ljava/lang/String;");
+ jfieldID valueField = env->GetFieldID(levelDbResultClass, "mValue", "Ljava/lang/String;");
+
+ std::string statusCode = getStatusCode(status);
+ env->SetObjectField(levelDbResultData, codeField, env->NewStringUTF(statusCode.c_str()));
+ env->SetObjectField(levelDbResultData, messageField,
+ env->NewStringUTF(status.ToString().c_str()));
+ env->SetObjectField(levelDbResultData, valueField, env->NewStringUTF(value.c_str()));
+ return levelDbResultData;
+}
+
+static leveldb::Status insertInLevelDB(JNIEnv* env, jobject obj, jlong leveldbptr,
+ jobject leveldbentry) {
+ jclass levelDbEntryClass = env->GetObjectClass(leveldbentry);
+ jmethodID getKeyMethodId =
+ env->GetMethodID(levelDbEntryClass, "getKey", "()Ljava/lang/String;");
+ jmethodID getValueMethodId =
+ env->GetMethodID(levelDbEntryClass, "getValue", "()Ljava/lang/String;");
+
+ jstring key = (jstring)env->CallObjectMethod(leveldbentry, getKeyMethodId);
+ jstring value = (jstring)env->CallObjectMethod(leveldbentry, getValueMethodId);
+ ScopedUtfChars utf_chars_key(env, key);
+ ScopedUtfChars utf_chars_value(env, value);
+ leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
+ leveldb::Status status;
+ status = leveldb->Put(leveldb::WriteOptions(), utf_chars_key.c_str(), utf_chars_value.c_str());
+ return status;
+}
+
+static jobject insert(JNIEnv* env, jobject obj, jlong leveldbptr, jobject leveldbentry) {
+ return createLevelDBResult(env, insertInLevelDB(env, obj, leveldbptr, leveldbentry), "");
+}
+
+/*
+ * Class: com_android_providers_media_leveldb_LevelDBInstance
+ * Method: nativeCreateInstance
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL
+ Java_com_android_providers_media_leveldb_LevelDBInstance_nativeCreateInstance(
+ JNIEnv* env, jclass leveldbInstanceClass, jstring path) {
+ ScopedUtfChars utf_chars_path(env, path);
+ leveldb::Options options;
+ options.create_if_missing = true;
+ leveldb::DB* leveldb;
+ leveldb::Status status = leveldb::DB::Open(options, utf_chars_path.c_str(), &leveldb);
+ if (status.ok()) {
+ return reinterpret_cast<jlong>(leveldb);
+ } else {
+ long val = 0;
+ return (jlong)val;
+ }
+}
+
+/*
+ * Class: com_android_providers_media_leveldb_LevelDBInstance
+ * Method: nativeQuery
+ * Signature: (JLjava/lang/String;)Lcom/android/providers/media/leveldb/LevelDBResult;
+ */
+JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeQuery(
+ JNIEnv* env, jobject obj, jlong leveldbptr, jstring path) {
+ ScopedUtfChars utf_chars_path(env, path);
+ leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
+ leveldb::Status status;
+ std::string value = "";
+ status = leveldb->Get(leveldb::ReadOptions(), utf_chars_path.c_str(), &value);
+ return createLevelDBResult(env, status, value);
+}
+
+/*
+ * Class: com_android_providers_media_leveldb_LevelDBInstance
+ * Method: nativeInsert
+ * Signature: (JLcom/android/providers/media/leveldb/LevelDBEntry;)
+ * Lcom/android/providers/media/leveldb/LevelDBResult;
+ */
+JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeInsert(
+ JNIEnv* env, jobject obj, jlong leveldbptr, jobject leveldbentry) {
+ return insert(env, obj, leveldbptr, leveldbentry);
+}
+
+/*
+ * Class: com_android_providers_media_leveldb_LevelDBInstance
+ * Method: nativeBulkInsert
+ * Signature: (JLjava/util/List;)Lcom/android/providers/media/leveldb/LevelDBResult;
+ */
+JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeBulkInsert(
+ JNIEnv* env, jobject obj, jlong leveldbptr, jobject entries) {
+ // Get the class of the list
+ jclass listClass = env->GetObjectClass(entries);
+
+ // Get the iterator method ID
+ jmethodID iteratorMethod = env->GetMethodID(listClass, "iterator", "()Ljava/util/Iterator;");
+
+ // Get the iterator object
+ jobject iterator = env->CallObjectMethod(entries, iteratorMethod);
+
+ // Get the iterator class
+ jclass iteratorClass = env->GetObjectClass(iterator);
+
+ // Get the hasNext and next method IDs
+ jmethodID hasNextMethod = env->GetMethodID(iteratorClass, "hasNext", "()Z");
+ jmethodID nextMethod = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
+
+ leveldb::Status status;
+
+ // Iterate through the list
+ while (env->CallBooleanMethod(iterator, hasNextMethod)) {
+ jobject jLevelDBEntryObject = env->CallObjectMethod(iterator, nextMethod);
+ leveldb::Status status = insertInLevelDB(env, obj, leveldbptr, jLevelDBEntryObject);
+ if (!status.ok()) {
+ break;
+ }
+ }
+
+ return createLevelDBResult(env, status, "");
+}
+
+/*
+ * Class: com_android_providers_media_leveldb_LevelDBInstance
+ * Method: nativeDelete
+ * Signature: (JLjava/lang/String;)Lcom/android/providers/media/leveldb/LevelDBResult;
+ */
+JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeDelete(
+ JNIEnv* env, jobject obj, jlong leveldbptr, jstring key) {
+ ScopedUtfChars utf_chars_key(env, key);
+ leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
+ leveldb::Status status;
+ status = leveldb->Delete(leveldb::WriteOptions(), utf_chars_key.c_str());
+ return createLevelDBResult(env, status, "");
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif