You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
implement Parcelable serialization using GVariantBuilder
This is needed for the error reporting notification intent in NewPipe now that we support persistent notifications.
This commit is contained in:
@@ -122,6 +122,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [
|
||||
'src/api-impl-jni/media/android_media_MediaPlayer.c',
|
||||
'src/api-impl-jni/media/android_media_session_MediaSession.c',
|
||||
'src/api-impl-jni/net/android_net_ConnectivityManager.c',
|
||||
'src/api-impl-jni/os/android_os_Parcel.c',
|
||||
'src/api-impl-jni/os/android_os_Process.c',
|
||||
'src/api-impl-jni/sensors/android_hardware_SensorManager.c',
|
||||
'src/api-impl-jni/text/android_text_Layout.c',
|
||||
|
||||
45
src/api-impl-jni/generated_headers/android_os_Parcel.h
Normal file
45
src/api-impl-jni/generated_headers/android_os_Parcel.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class android_os_Parcel */
|
||||
|
||||
#ifndef _Included_android_os_Parcel
|
||||
#define _Included_android_os_Parcel
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: android_os_Parcel
|
||||
* Method: native_writeInt
|
||||
* Signature: (JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_os_Parcel_native_1writeInt
|
||||
(JNIEnv *, jclass, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: android_os_Parcel
|
||||
* Method: native_writeString
|
||||
* Signature: (JLjava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_os_Parcel_native_1writeString
|
||||
(JNIEnv *, jclass, jlong, jstring);
|
||||
|
||||
/*
|
||||
* Class: android_os_Parcel
|
||||
* Method: native_readInt
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_android_os_Parcel_native_1readInt
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_os_Parcel
|
||||
* Method: native_readString
|
||||
* Signature: (J)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_android_os_Parcel_native_1readString
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -124,6 +124,7 @@ void set_up_handle_cache(JNIEnv *env)
|
||||
handle_cache.intent.putExtraByteArray = _METHOD(handle_cache.intent.class, "putExtra", "(Ljava/lang/String;[B)Landroid/content/Intent;");
|
||||
handle_cache.intent.putExtraInt = _METHOD(handle_cache.intent.class, "putExtra", "(Ljava/lang/String;I)Landroid/content/Intent;");
|
||||
handle_cache.intent.putExtraLong = _METHOD(handle_cache.intent.class, "putExtra", "(Ljava/lang/String;J)Landroid/content/Intent;");
|
||||
handle_cache.intent.putExtraParcelable = _METHOD(handle_cache.intent.class, "putExtra", "(Ljava/lang/String;Landroid/os/Parcelable;)Landroid/content/Intent;");
|
||||
handle_cache.intent.getDataString = _METHOD(handle_cache.intent.class, "getDataString", "()Ljava/lang/String;");
|
||||
handle_cache.intent.setClassName = _METHOD(handle_cache.intent.class, "setClassName", "(Landroid/content/Context;Ljava/lang/String;)Landroid/content/Intent;");
|
||||
|
||||
@@ -145,4 +146,9 @@ void set_up_handle_cache(JNIEnv *env)
|
||||
|
||||
handle_cache.set.class = _REF((*env)->FindClass(env, "java/util/Set"));
|
||||
handle_cache.set.toArray = _METHOD(handle_cache.set.class, "toArray", "()[Ljava/lang/Object;");
|
||||
|
||||
handle_cache.parcel.class = _REF((*env)->FindClass(env, "android/os/Parcel"));
|
||||
handle_cache.parcel.constructor = _METHOD(handle_cache.parcel.class, "<init>", "(JJ)V");
|
||||
handle_cache.parcel.writeParcelable = _METHOD(handle_cache.parcel.class, "writeParcelable", "(Landroid/os/Parcelable;I)V");
|
||||
handle_cache.parcel.readParcelable = _METHOD(handle_cache.parcel.class, "readParcelable", "(Ljava/lang/ClassLoader;)Landroid/os/Parcelable;");
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ struct handle_cache {
|
||||
jmethodID putExtraByteArray;
|
||||
jmethodID putExtraInt;
|
||||
jmethodID putExtraLong;
|
||||
jmethodID putExtraParcelable;
|
||||
jmethodID getDataString;
|
||||
jmethodID setClassName;
|
||||
} intent;
|
||||
@@ -157,6 +158,12 @@ struct handle_cache {
|
||||
jclass class;
|
||||
jmethodID toArray;
|
||||
} set;
|
||||
struct {
|
||||
jclass class;
|
||||
jmethodID constructor;
|
||||
jmethodID writeParcelable;
|
||||
jmethodID readParcelable;
|
||||
} parcel;
|
||||
};
|
||||
|
||||
extern struct handle_cache handle_cache;
|
||||
|
||||
37
src/api-impl-jni/os/android_os_Parcel.c
Normal file
37
src/api-impl-jni/os/android_os_Parcel.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include "../defines.h"
|
||||
|
||||
#include "../generated_headers/android_os_Parcel.h"
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_os_Parcel_native_1writeInt(JNIEnv *env, jclass clazz, jlong builder_ptr, jint value)
|
||||
{
|
||||
GVariantBuilder *builder = (GVariantBuilder *)builder_ptr;
|
||||
if (builder)
|
||||
g_variant_builder_add(builder, "i", value);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_os_Parcel_native_1writeString(JNIEnv *env, jclass clazz, jlong builder_ptr, jstring value)
|
||||
{
|
||||
GVariantBuilder *builder = (GVariantBuilder *)builder_ptr;
|
||||
if (builder)
|
||||
g_variant_builder_add(builder, "s", (*env)->GetStringUTFChars(env, value, NULL));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_android_os_Parcel_native_1readInt(JNIEnv *env, jclass clazz, jlong iter_ptr)
|
||||
{
|
||||
GVariantIter *iter = (GVariantIter *)iter_ptr;
|
||||
jint i = 0;
|
||||
if (iter)
|
||||
g_variant_iter_next(iter, "i", &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_android_os_Parcel_native_1readString(JNIEnv *env, jclass clazz, jlong iter_ptr)
|
||||
{
|
||||
GVariantIter *iter = (GVariantIter *)iter_ptr;
|
||||
const char *s = NULL;
|
||||
if (iter)
|
||||
g_variant_iter_next(iter, "s", &s);
|
||||
return s ? _JSTRING(s) : NULL;
|
||||
}
|
||||
@@ -257,18 +257,27 @@ GVariant *intent_serialize(JNIEnv *env, jobject intent) {
|
||||
jobject extras_key_set = (*env)->CallObjectMethod(env, extras, handle_cache.bundle.keySet);
|
||||
jobjectArray extras_keys = (*env)->CallObjectMethod(env, extras_key_set, handle_cache.set.toArray);
|
||||
jsize extras_keys_length = (*env)->GetArrayLength(env, extras_keys);
|
||||
jclass parcelable_class = (*env)->FindClass(env, "android/os/Parcelable");
|
||||
for (jint i = 0; i < extras_keys_length; i++) {
|
||||
jstring key_jstr = (*env)->GetObjectArrayElement(env, extras_keys, i);
|
||||
jobject value_jobj = (*env)->CallObjectMethod(env, extras, handle_cache.bundle.get, key_jstr);
|
||||
if (!(*env)->IsSameObject(env, _CLASS(key_jstr), _CLASS(value_jobj))) {
|
||||
printf("skipping non-string extra: %s\n", (*env)->GetStringUTFChars(env, key_jstr, NULL));
|
||||
continue;
|
||||
}
|
||||
const char *key = (*env)->GetStringUTFChars(env, key_jstr, NULL);
|
||||
const char *value = (*env)->GetStringUTFChars(env, value_jobj, NULL);
|
||||
g_variant_builder_add(&extras_builder, "{sv}", key, g_variant_new_string(value));
|
||||
if ((*env)->IsInstanceOf(env, value_jobj, _CLASS(key_jstr))) {
|
||||
const char *value = (*env)->GetStringUTFChars(env, value_jobj, NULL);
|
||||
g_variant_builder_add(&extras_builder, "{sv}", key, g_variant_new_string(value));
|
||||
(*env)->ReleaseStringUTFChars(env, value_jobj, value);
|
||||
} else if ((*env)->IsInstanceOf(env, value_jobj, parcelable_class)) {
|
||||
GVariantBuilder parcel_builder;
|
||||
g_variant_builder_init_static(&parcel_builder, G_VARIANT_TYPE_TUPLE);
|
||||
jobject parcel = (*env)->NewObject(env, handle_cache.parcel.class, handle_cache.parcel.constructor, _INTPTR(&parcel_builder), 0);
|
||||
(*env)->CallVoidMethod(env, parcel, handle_cache.parcel.writeParcelable, value_jobj, 0);
|
||||
GVariant *parcel_variant = g_variant_builder_end(&parcel_builder);
|
||||
g_variant_builder_add(&extras_builder, "{sv}", key, parcel_variant);
|
||||
(*env)->DeleteLocalRef(env, parcel);
|
||||
} else {
|
||||
printf("intent_serialize: skipping non-string, non-parcelable extra: %s\n", key);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, key_jstr, key);
|
||||
(*env)->ReleaseStringUTFChars(env, value_jobj, value);
|
||||
(*env)->DeleteLocalRef(env, key_jstr);
|
||||
(*env)->DeleteLocalRef(env, value_jobj);
|
||||
}
|
||||
@@ -323,6 +332,20 @@ jobject intent_deserialize(JNIEnv *env, GVariant *variant) {
|
||||
jbyteArray bytesMessage = (*env)->NewByteArray(env, size);
|
||||
(*env)->SetByteArrayRegion(env, bytesMessage, 0, size, message);
|
||||
(*env)->CallObjectMethod(env, intent, handle_cache.intent.putExtraByteArray, _JSTRING(key), bytesMessage);
|
||||
} else if (g_variant_is_of_type(value, G_VARIANT_TYPE_TUPLE)) {
|
||||
GVariantIter parcel_iter;
|
||||
g_variant_iter_init(&parcel_iter, value);
|
||||
jobject parcel = (*env)->NewObject(env, handle_cache.parcel.class, handle_cache.parcel.constructor, 0, _INTPTR(&parcel_iter));
|
||||
jmethodID getClassLoader = _METHOD((*env)->FindClass(env, "java/lang/Class"), "getClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
jobject class_loader = (*env)->CallObjectMethod(env, handle_cache.parcel.class, getClassLoader);
|
||||
jobject parcelable = (*env)->CallObjectMethod(env, parcel, handle_cache.parcel.readParcelable, class_loader);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
(*env)->CallObjectMethod(env, intent, handle_cache.intent.putExtraParcelable, _JSTRING(key), parcelable);
|
||||
(*env)->DeleteLocalRef(env, parcelable);
|
||||
(*env)->DeleteLocalRef(env, parcel);
|
||||
}
|
||||
}
|
||||
g_variant_iter_free(extras);
|
||||
|
||||
@@ -5,8 +5,16 @@ import java.util.List;
|
||||
|
||||
public class Parcel {
|
||||
|
||||
private long builder;
|
||||
private long iter;
|
||||
|
||||
Parcel(long builder, long iter) {
|
||||
this.builder = builder;
|
||||
this.iter = iter;
|
||||
}
|
||||
|
||||
public static Parcel obtain() {
|
||||
return new Parcel();
|
||||
return new Parcel(0, 0);
|
||||
}
|
||||
|
||||
public void writeBundle(Bundle bundle) {}
|
||||
@@ -25,6 +33,7 @@ public class Parcel {
|
||||
|
||||
public void writeString(String s) {
|
||||
System.out.println("Parcel.writeString(" + s + ")");
|
||||
native_writeString(builder, s);
|
||||
}
|
||||
|
||||
public void writeLong(long l) {
|
||||
@@ -33,6 +42,7 @@ public class Parcel {
|
||||
|
||||
public void writeInt(int i) {
|
||||
System.out.println("Parcel.writeInt(" + i + ")");
|
||||
native_writeInt(builder, i);
|
||||
}
|
||||
|
||||
public byte[] marshall() {
|
||||
@@ -45,6 +55,8 @@ public class Parcel {
|
||||
|
||||
public void writeParcelable(Parcelable p, int flags) {
|
||||
System.out.println("Parcel.writeParcelable(" + p + ", " + flags + ")");
|
||||
native_writeString(builder, p.getClass().getName());
|
||||
p.writeToParcel(this, flags);
|
||||
}
|
||||
|
||||
public void writeInterfaceToken(String s) {
|
||||
@@ -66,7 +78,7 @@ public class Parcel {
|
||||
public void unmarshall(byte[] data, int offset, int length) {}
|
||||
|
||||
public String readString() {
|
||||
return "fixme: Parcel.readString()";
|
||||
return native_readString(iter);
|
||||
}
|
||||
|
||||
public byte readByte() {
|
||||
@@ -77,11 +89,40 @@ public class Parcel {
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
|
||||
public Parcelable readParcelable(ClassLoader loader) {
|
||||
return null;
|
||||
public Parcelable readParcelable(ClassLoader loader) throws ReflectiveOperationException {
|
||||
String className = native_readString(iter);
|
||||
@SuppressWarnings("unchecked")
|
||||
Parcelable.Creator<Parcelable> creator = loader.loadClass(className + "$Creator").asSubclass(Parcelable.Creator.class).getConstructor().newInstance();
|
||||
return creator.createFromParcel(this);
|
||||
}
|
||||
|
||||
public void writeStrongBinder(IBinder binder) {}
|
||||
|
||||
public void readException() {}
|
||||
|
||||
public int readInt() {
|
||||
return native_readInt(iter);
|
||||
}
|
||||
|
||||
public void writeStringArray(String[] strings) {
|
||||
System.out.println("Parcel.writeStringArray(" + strings + ")");
|
||||
native_writeInt(builder, strings.length);
|
||||
for (String s : strings) {
|
||||
native_writeString(builder, s);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] createStringArray() {
|
||||
int len = native_readInt(iter);
|
||||
String[] strings = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
strings[i] = native_readString(iter);
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
protected static native void native_writeInt(long builder, int i);
|
||||
protected static native void native_writeString(long builder, String s);
|
||||
protected static native int native_readInt(long iter);
|
||||
protected static native String native_readString(long iter);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user