diff options
author | Cassie Wang <cassiewang@google.com> | 2020-01-20 22:39:24 -0800 |
---|---|---|
committer | Cassie Wang <cassiewang@google.com> | 2020-02-28 14:45:01 -0800 |
commit | 43fec62894253136f0c8b6a0aa5132ddff6edaf7 (patch) | |
tree | 273f7807c68629771d1a03344ab17d207ae212b9 /icing | |
parent | 8d99a2d3b71f111de0d83608c31ec3dc2ef29d3d (diff) | |
download | icing-43fec62894253136f0c8b6a0aa5132ddff6edaf7.tar.gz |
Create JNI layer for Icing
Bug: 146383629
Test: manual 'atest
java/tests/instrumentation/src/com/google/android/icing/IcingSearchEngineTest.java'
Change-Id: I3868ca19a477bd6996f268d2a73a1dc906afaee6
Diffstat (limited to 'icing')
-rw-r--r-- | icing/icing-search-engine_jni.cc | 285 | ||||
-rw-r--r-- | icing/jni.lds | 10 |
2 files changed, 295 insertions, 0 deletions
diff --git a/icing/icing-search-engine_jni.cc b/icing/icing-search-engine_jni.cc new file mode 100644 index 0000000..263c4f9 --- /dev/null +++ b/icing/icing-search-engine_jni.cc @@ -0,0 +1,285 @@ +// Copyright (C) 2020 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. + +#include <google/protobuf/message_lite.h> +#include <jni.h> + +#include <string> + +#include "icing/absl_ports/status_imports.h" +#include "icing/icing-search-engine.h" +#include "icing/proto/document.pb.h" +#include "icing/proto/initialize.pb.h" +#include "icing/proto/optimize.pb.h" +#include "icing/proto/persist.pb.h" +#include "icing/proto/schema.pb.h" +#include "icing/proto/search.pb.h" +#include "icing/util/logging.h" + +namespace { + +bool ParseProtoFromJniByteArray(JNIEnv* env, jbyteArray bytes, + google::protobuf::MessageLite* protobuf) { + int bytes_size = env->GetArrayLength(bytes); + uint8_t* bytes_ptr = static_cast<uint8_t*>( + env->GetPrimitiveArrayCritical(bytes, /*isCopy=*/nullptr)); + bool parsed = protobuf->ParseFromArray(bytes_ptr, bytes_size); + env->ReleasePrimitiveArrayCritical(bytes, bytes_ptr, /*mode=*/0); + + return parsed; +} + +jbyteArray SerializeProtoToJniByteArray( + JNIEnv* env, const google::protobuf::MessageLite& protobuf) { + int size = protobuf.ByteSizeLong(); + jbyteArray ret = env->NewByteArray(size); + if (ret == nullptr) { + ICING_LOG(ERROR) << "Failed to allocated bytes for jni protobuf"; + return nullptr; + } + + uint8_t* ret_buf = static_cast<uint8_t*>( + env->GetPrimitiveArrayCritical(ret, /*isCopy=*/nullptr)); + protobuf.SerializeWithCachedSizesToArray(ret_buf); + env->ReleasePrimitiveArrayCritical(ret, ret_buf, 0); + return ret; +} + +icing::lib::IcingSearchEngine* GetIcingSearchEnginePointer( + jlong native_pointer) { + return reinterpret_cast<icing::lib::IcingSearchEngine*>(native_pointer); +} + +} // namespace + +extern "C" { + +jint JNI_OnLoad(JavaVM* vm, void* reserved) { + JNIEnv* env; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { + ICING_LOG(ERROR) << "ERROR: GetEnv failed"; + return JNI_ERR; + } + + return JNI_VERSION_1_6; +} + +JNIEXPORT jlong JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeCreate( + JNIEnv* env, jobject obj, jbyteArray icing_search_engine_options_bytes) { + icing::lib::IcingSearchEngineOptions options; + if (!ParseProtoFromJniByteArray(env, icing_search_engine_options_bytes, + &options)) { + ICING_LOG(ERROR) + << "Failed to parse IcingSearchEngineOptions in nativeCreate"; + return 0; + } + + icing::lib::IcingSearchEngine* icing = + new icing::lib::IcingSearchEngine(options); + return reinterpret_cast<jlong>(icing); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeInitialize( + JNIEnv* env, jobject obj, jlong native_pointer) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + icing::lib::InitializeResultProto initialize_result_proto = + icing->Initialize(); + + return SerializeProtoToJniByteArray(env, initialize_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeSetSchema( + JNIEnv* env, jobject obj, jlong native_pointer, jbyteArray schema_bytes, + jboolean ignore_errors_and_delete_documents) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + icing::lib::SchemaProto schema_proto; + if (!ParseProtoFromJniByteArray(env, schema_bytes, &schema_proto)) { + ICING_LOG(ERROR) << "Failed to parse SchemaProto in nativeSetSchema"; + return nullptr; + } + + icing::lib::SetSchemaResultProto set_schema_result_proto = + icing->SetSchema(schema_proto, ignore_errors_and_delete_documents); + + return SerializeProtoToJniByteArray(env, set_schema_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeGetSchema( + JNIEnv* env, jobject obj, jlong native_pointer) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + icing::lib::GetSchemaResultProto get_schema_result_proto = icing->GetSchema(); + + return SerializeProtoToJniByteArray(env, get_schema_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeGetSchemaType( + JNIEnv* env, jobject obj, jlong native_pointer, jstring schema_type) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + const char* native_schema_type = + env->GetStringUTFChars(schema_type, /*isCopy=*/nullptr); + icing::lib::GetSchemaTypeResultProto get_schema_type_result_proto = + icing->GetSchemaType(native_schema_type); + + return SerializeProtoToJniByteArray(env, get_schema_type_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativePut( + JNIEnv* env, jobject obj, jlong native_pointer, jbyteArray document_bytes) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + icing::lib::DocumentProto document_proto; + if (!ParseProtoFromJniByteArray(env, document_bytes, &document_proto)) { + ICING_LOG(ERROR) << "Failed to parse DocumentProto in nativePut"; + return nullptr; + } + + icing::lib::PutResultProto put_result_proto = icing->Put(document_proto); + + return SerializeProtoToJniByteArray(env, put_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeGet(JNIEnv* env, + jobject obj, + jlong native_pointer, + jstring name_space, + jstring uri) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + const char* native_name_space = + env->GetStringUTFChars(name_space, /*isCopy=*/nullptr); + const char* native_uri = env->GetStringUTFChars(uri, /*isCopy=*/nullptr); + icing::lib::GetResultProto get_result_proto = + icing->Get(native_name_space, native_uri); + + return SerializeProtoToJniByteArray(env, get_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeSearch( + JNIEnv* env, jobject obj, jlong native_pointer, + jbyteArray search_spec_bytes, jbyteArray scoring_spec_bytes, + jbyteArray result_spec_bytes) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + icing::lib::SearchSpecProto search_spec_proto; + if (!ParseProtoFromJniByteArray(env, search_spec_bytes, &search_spec_proto)) { + ICING_LOG(ERROR) << "Failed to parse SearchSpecProto in nativeSearch"; + return nullptr; + } + + icing::lib::ScoringSpecProto scoring_spec_proto; + if (!ParseProtoFromJniByteArray(env, scoring_spec_bytes, + &scoring_spec_proto)) { + ICING_LOG(ERROR) << "Failed to parse ScoringSpecProto in nativeSearch"; + return nullptr; + } + + icing::lib::ResultSpecProto result_spec_proto; + if (!ParseProtoFromJniByteArray(env, result_spec_bytes, &result_spec_proto)) { + ICING_LOG(ERROR) << "Failed to parse ResultSpecProto in nativeSearch"; + return nullptr; + } + + icing::lib::SearchResultProto search_result_proto = + icing->Search(search_spec_proto, scoring_spec_proto, result_spec_proto); + + return SerializeProtoToJniByteArray(env, search_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeDelete( + JNIEnv* env, jobject obj, jlong native_pointer, jstring name_space, + jstring uri) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + const char* native_name_space = + env->GetStringUTFChars(name_space, /*isCopy=*/nullptr); + const char* native_uri = env->GetStringUTFChars(uri, /*isCopy=*/nullptr); + icing::lib::DeleteResultProto delete_result_proto = + icing->Delete(native_name_space, native_uri); + + return SerializeProtoToJniByteArray(env, delete_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeDeleteByNamespace( + JNIEnv* env, jobject obj, jlong native_pointer, jstring name_space) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + const char* native_name_space = + env->GetStringUTFChars(name_space, /*isCopy=*/nullptr); + icing::lib::DeleteByNamespaceResultProto delete_by_namespace_result_proto = + icing->DeleteByNamespace(native_name_space); + + return SerializeProtoToJniByteArray(env, delete_by_namespace_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeDeleteBySchemaType( + JNIEnv* env, jobject obj, jlong native_pointer, jstring schema_type) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + const char* native_schema_type = + env->GetStringUTFChars(schema_type, /*isCopy=*/nullptr); + icing::lib::DeleteBySchemaTypeResultProto delete_by_schema_type_result_proto = + icing->DeleteBySchemaType(native_schema_type); + + return SerializeProtoToJniByteArray(env, delete_by_schema_type_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativePersistToDisk( + JNIEnv* env, jobject obj, jlong native_pointer) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + icing::lib::PersistToDiskResultProto persist_to_disk_result_proto = + icing->PersistToDisk(); + + return SerializeProtoToJniByteArray(env, persist_to_disk_result_proto); +} + +JNIEXPORT jbyteArray JNICALL +Java_com_google_android_icing_IcingSearchEngine_nativeOptimize( + JNIEnv* env, jobject obj, jlong native_pointer) { + icing::lib::IcingSearchEngine* icing = + GetIcingSearchEnginePointer(native_pointer); + + icing::lib::OptimizeResultProto optimize_result_proto = icing->Optimize(); + + return SerializeProtoToJniByteArray(env, optimize_result_proto); +} + +} // extern "C" diff --git a/icing/jni.lds b/icing/jni.lds new file mode 100644 index 0000000..401682a --- /dev/null +++ b/icing/jni.lds @@ -0,0 +1,10 @@ +VERS_1.0 { + # Export JNI symbols. + global: + Java_*; + JNI_OnLoad; + + # Hide everything else + local: + *; +}; |