diff options
author | 2024-04-03 12:58:05 +0000 | |
---|---|---|
committer | 2024-05-10 12:12:31 +0000 | |
commit | 16b87803e0b0ecab9434a37fbfd12da36d5d8d16 (patch) | |
tree | a64796b397158fae364831aaa9ec689e552a0ece /jni | |
parent | a81809af62af64f12a8120057aa59177d22717e7 (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.bp | 81 | ||||
-rw-r--r-- | jni/com_android_providers_media_leveldb_LevelDBInstance.cpp | 168 |
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 |