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_MediaPlayer.c',
|
||||||
'src/api-impl-jni/media/android_media_session_MediaSession.c',
|
'src/api-impl-jni/media/android_media_session_MediaSession.c',
|
||||||
'src/api-impl-jni/net/android_net_ConnectivityManager.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/os/android_os_Process.c',
|
||||||
'src/api-impl-jni/sensors/android_hardware_SensorManager.c',
|
'src/api-impl-jni/sensors/android_hardware_SensorManager.c',
|
||||||
'src/api-impl-jni/text/android_text_Layout.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.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.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.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.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;");
|
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.class = _REF((*env)->FindClass(env, "java/util/Set"));
|
||||||
handle_cache.set.toArray = _METHOD(handle_cache.set.class, "toArray", "()[Ljava/lang/Object;");
|
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 putExtraByteArray;
|
||||||
jmethodID putExtraInt;
|
jmethodID putExtraInt;
|
||||||
jmethodID putExtraLong;
|
jmethodID putExtraLong;
|
||||||
|
jmethodID putExtraParcelable;
|
||||||
jmethodID getDataString;
|
jmethodID getDataString;
|
||||||
jmethodID setClassName;
|
jmethodID setClassName;
|
||||||
} intent;
|
} intent;
|
||||||
@@ -157,6 +158,12 @@ struct handle_cache {
|
|||||||
jclass class;
|
jclass class;
|
||||||
jmethodID toArray;
|
jmethodID toArray;
|
||||||
} set;
|
} set;
|
||||||
|
struct {
|
||||||
|
jclass class;
|
||||||
|
jmethodID constructor;
|
||||||
|
jmethodID writeParcelable;
|
||||||
|
jmethodID readParcelable;
|
||||||
|
} parcel;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct handle_cache handle_cache;
|
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);
|
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);
|
jobjectArray extras_keys = (*env)->CallObjectMethod(env, extras_key_set, handle_cache.set.toArray);
|
||||||
jsize extras_keys_length = (*env)->GetArrayLength(env, extras_keys);
|
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++) {
|
for (jint i = 0; i < extras_keys_length; i++) {
|
||||||
jstring key_jstr = (*env)->GetObjectArrayElement(env, extras_keys, i);
|
jstring key_jstr = (*env)->GetObjectArrayElement(env, extras_keys, i);
|
||||||
jobject value_jobj = (*env)->CallObjectMethod(env, extras, handle_cache.bundle.get, key_jstr);
|
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 *key = (*env)->GetStringUTFChars(env, key_jstr, NULL);
|
||||||
const char *value = (*env)->GetStringUTFChars(env, value_jobj, NULL);
|
if ((*env)->IsInstanceOf(env, value_jobj, _CLASS(key_jstr))) {
|
||||||
g_variant_builder_add(&extras_builder, "{sv}", key, g_variant_new_string(value));
|
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, key_jstr, key);
|
||||||
(*env)->ReleaseStringUTFChars(env, value_jobj, value);
|
|
||||||
(*env)->DeleteLocalRef(env, key_jstr);
|
(*env)->DeleteLocalRef(env, key_jstr);
|
||||||
(*env)->DeleteLocalRef(env, value_jobj);
|
(*env)->DeleteLocalRef(env, value_jobj);
|
||||||
}
|
}
|
||||||
@@ -323,6 +332,20 @@ jobject intent_deserialize(JNIEnv *env, GVariant *variant) {
|
|||||||
jbyteArray bytesMessage = (*env)->NewByteArray(env, size);
|
jbyteArray bytesMessage = (*env)->NewByteArray(env, size);
|
||||||
(*env)->SetByteArrayRegion(env, bytesMessage, 0, size, message);
|
(*env)->SetByteArrayRegion(env, bytesMessage, 0, size, message);
|
||||||
(*env)->CallObjectMethod(env, intent, handle_cache.intent.putExtraByteArray, _JSTRING(key), bytesMessage);
|
(*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);
|
g_variant_iter_free(extras);
|
||||||
|
|||||||
@@ -5,8 +5,16 @@ import java.util.List;
|
|||||||
|
|
||||||
public class Parcel {
|
public class Parcel {
|
||||||
|
|
||||||
|
private long builder;
|
||||||
|
private long iter;
|
||||||
|
|
||||||
|
Parcel(long builder, long iter) {
|
||||||
|
this.builder = builder;
|
||||||
|
this.iter = iter;
|
||||||
|
}
|
||||||
|
|
||||||
public static Parcel obtain() {
|
public static Parcel obtain() {
|
||||||
return new Parcel();
|
return new Parcel(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeBundle(Bundle bundle) {}
|
public void writeBundle(Bundle bundle) {}
|
||||||
@@ -25,6 +33,7 @@ public class Parcel {
|
|||||||
|
|
||||||
public void writeString(String s) {
|
public void writeString(String s) {
|
||||||
System.out.println("Parcel.writeString(" + s + ")");
|
System.out.println("Parcel.writeString(" + s + ")");
|
||||||
|
native_writeString(builder, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeLong(long l) {
|
public void writeLong(long l) {
|
||||||
@@ -33,6 +42,7 @@ public class Parcel {
|
|||||||
|
|
||||||
public void writeInt(int i) {
|
public void writeInt(int i) {
|
||||||
System.out.println("Parcel.writeInt(" + i + ")");
|
System.out.println("Parcel.writeInt(" + i + ")");
|
||||||
|
native_writeInt(builder, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] marshall() {
|
public byte[] marshall() {
|
||||||
@@ -45,6 +55,8 @@ public class Parcel {
|
|||||||
|
|
||||||
public void writeParcelable(Parcelable p, int flags) {
|
public void writeParcelable(Parcelable p, int flags) {
|
||||||
System.out.println("Parcel.writeParcelable(" + p + ", " + flags + ")");
|
System.out.println("Parcel.writeParcelable(" + p + ", " + flags + ")");
|
||||||
|
native_writeString(builder, p.getClass().getName());
|
||||||
|
p.writeToParcel(this, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeInterfaceToken(String s) {
|
public void writeInterfaceToken(String s) {
|
||||||
@@ -66,7 +78,7 @@ public class Parcel {
|
|||||||
public void unmarshall(byte[] data, int offset, int length) {}
|
public void unmarshall(byte[] data, int offset, int length) {}
|
||||||
|
|
||||||
public String readString() {
|
public String readString() {
|
||||||
return "fixme: Parcel.readString()";
|
return native_readString(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte readByte() {
|
public byte readByte() {
|
||||||
@@ -77,11 +89,40 @@ public class Parcel {
|
|||||||
return new ArrayList<String>();
|
return new ArrayList<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parcelable readParcelable(ClassLoader loader) {
|
public Parcelable readParcelable(ClassLoader loader) throws ReflectiveOperationException {
|
||||||
return null;
|
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 writeStrongBinder(IBinder binder) {}
|
||||||
|
|
||||||
public void readException() {}
|
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