| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/segmentation_platform/public/android/input_context_android.h" |
| |
| #include <jni.h> |
| #include <cstddef> |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| #include "base/android/jni_android.h" |
| #include "base/android/jni_array.h" |
| #include "base/android/jni_string.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/check.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/time/time.h" |
| #include "components/segmentation_platform/public/input_context.h" |
| #include "components/segmentation_platform/public/types/processed_value.h" |
| #include "url/android/gurl_android.h" |
| #include "url/gurl.h" |
| |
| // Must come after all headers that specialize FromJniType() / ToJniType(). |
| #include "components/segmentation_platform/public/jni_headers/InputContext_jni.h" |
| |
| using base::android::JavaParamRef; |
| |
| namespace segmentation_platform { |
| |
| namespace { |
| |
| // Takes a pair of java arrays with keys and values, converts them to native |
| // types and inserts then at the given InputContext. Keys are always strings. |
| // Values are converted from a java array of type JV (e.g. jintArray) to an |
| // std::vector<NV> where NV is a native value type (e.g. int). A function to |
| // convert from java array to vector of native values is required. |
| template <class JV, class NV> |
| void ConvertAndAddToInputContext( |
| JNIEnv* env, |
| InputContext* input_context, |
| const base::android::JavaRef<jobjectArray>& java_keys, |
| const base::android::JavaRef<JV>& java_values, |
| void (*converter)(JNIEnv*, |
| const base::android::JavaRef<JV>&, |
| std::vector<NV>*)) { |
| std::vector<std::string> native_keys; |
| std::vector<NV> native_values; |
| |
| base::android::AppendJavaStringArrayToStringVector(env, java_keys, |
| &native_keys); |
| converter(env, java_values, &native_values); |
| |
| CHECK(native_keys.size() == native_values.size()) |
| << "Key and value count must be equal: " << native_keys.size() |
| << " != " << native_values.size(); |
| |
| for (size_t i = 0; i < native_keys.size(); i++) { |
| input_context->metadata_args.emplace(native_keys[i], native_values[i]); |
| } |
| } |
| |
| void JavaGURLArrayToGURLVector( |
| JNIEnv* env, |
| const base::android::JavaRef<jobjectArray>& j_gurls, |
| std::vector<GURL>* ret) { |
| *ret = jni_zero::FromJniArray<std::vector<GURL>>(env, j_gurls); |
| } |
| |
| static void JavaLongArrayToBaseTimeVector( |
| JNIEnv* env, |
| const base::android::JavaRef<jlongArray>& java_values, |
| std::vector<base::Time>* out_times) { |
| std::vector<int64_t> time_values; |
| base::android::JavaLongArrayToInt64Vector(env, java_values, &time_values); |
| for (int64_t time_value : time_values) { |
| out_times->emplace_back( |
| base::Time::FromMillisecondsSinceUnixEpoch(time_value)); |
| } |
| } |
| |
| } // namespace |
| |
| // static |
| scoped_refptr<InputContext> InputContextAndroid::ToNativeInputContext( |
| JNIEnv* env, |
| const base::android::JavaRef<jobject>& j_input_context) { |
| if (!j_input_context) { |
| return nullptr; |
| } |
| scoped_refptr<InputContext> input_context = |
| base::MakeRefCounted<InputContext>(); |
| Java_InputContext_fillNativeInputContext( |
| env, j_input_context, reinterpret_cast<intptr_t>(input_context.get())); |
| |
| return input_context; |
| } |
| |
| void InputContextAndroid::FromJavaParams( |
| JNIEnv* env, |
| const jlong input_context_ptr, |
| const base::android::JavaRef<jobjectArray>& jboolean_keys, |
| const base::android::JavaRef<jbooleanArray>& jboolean_values, |
| const base::android::JavaRef<jobjectArray>& jint_keys, |
| const base::android::JavaRef<jintArray>& jint_values, |
| const base::android::JavaRef<jobjectArray>& jfloat_keys, |
| const base::android::JavaRef<jfloatArray>& jfloat_values, |
| const base::android::JavaRef<jobjectArray>& jdouble_keys, |
| const base::android::JavaRef<jdoubleArray>& jdouble_values, |
| const base::android::JavaRef<jobjectArray>& jstring_keys, |
| const base::android::JavaRef<jobjectArray>& jstring_values, |
| const base::android::JavaRef<jobjectArray>& jtime_keys, |
| const base::android::JavaRef<jlongArray>& jtime_values, |
| const base::android::JavaRef<jobjectArray>& jint64_keys, |
| const base::android::JavaRef<jlongArray>& jint64_values, |
| const base::android::JavaRef<jobjectArray>& jurl_keys, |
| const base::android::JavaRef<jobjectArray>& jurl_values) { |
| InputContext* input_context = |
| reinterpret_cast<InputContext*>(input_context_ptr); |
| |
| ConvertAndAddToInputContext(env, input_context, jboolean_keys, |
| jboolean_values, |
| base::android::JavaBooleanArrayToBoolVector); |
| ConvertAndAddToInputContext(env, input_context, jint_keys, jint_values, |
| base::android::JavaIntArrayToIntVector); |
| ConvertAndAddToInputContext(env, input_context, jfloat_keys, jfloat_values, |
| base::android::JavaFloatArrayToFloatVector); |
| ConvertAndAddToInputContext(env, input_context, jdouble_keys, jdouble_values, |
| base::android::JavaDoubleArrayToDoubleVector); |
| ConvertAndAddToInputContext<jobjectArray, std::string>( |
| env, input_context, jstring_keys, jstring_values, |
| base::android::AppendJavaStringArrayToStringVector); |
| ConvertAndAddToInputContext(env, input_context, jtime_keys, jtime_values, |
| JavaLongArrayToBaseTimeVector); |
| ConvertAndAddToInputContext(env, input_context, jint64_keys, jint64_values, |
| base::android::JavaLongArrayToInt64Vector); |
| ConvertAndAddToInputContext(env, input_context, jurl_keys, jurl_values, |
| JavaGURLArrayToGURLVector); |
| } |
| |
| static void JNI_InputContext_FillNative( |
| JNIEnv* env, |
| const jlong input_context_ptr, |
| const JavaParamRef<jobjectArray>& jboolean_keys, |
| const JavaParamRef<jbooleanArray>& jboolean_values, |
| const JavaParamRef<jobjectArray>& jint_keys, |
| const JavaParamRef<jintArray>& jint_values, |
| const JavaParamRef<jobjectArray>& jfloat_keys, |
| const JavaParamRef<jfloatArray>& jfloat_values, |
| const JavaParamRef<jobjectArray>& jdouble_keys, |
| const JavaParamRef<jdoubleArray>& jdouble_values, |
| const JavaParamRef<jobjectArray>& jstring_keys, |
| const JavaParamRef<jobjectArray>& jstring_values, |
| const JavaParamRef<jobjectArray>& jtime_keys, |
| const JavaParamRef<jlongArray>& jtime_values, |
| const JavaParamRef<jobjectArray>& jint64_keys, |
| const JavaParamRef<jlongArray>& jint64_values, |
| const JavaParamRef<jobjectArray>& jurl_keys, |
| const JavaParamRef<jobjectArray>& jurl_values) { |
| segmentation_platform::InputContextAndroid::FromJavaParams( |
| env, input_context_ptr, jboolean_keys, jboolean_values, jint_keys, |
| jint_values, jfloat_keys, jfloat_values, jdouble_keys, jdouble_values, |
| jstring_keys, jstring_values, jtime_keys, jtime_values, jint64_keys, |
| jint64_values, jurl_keys, jurl_values); |
| } |
| |
| } // namespace segmentation_platform |