Merge "Remove InputChannel.finalize() by using NativeAllocationRegistry"

This commit is contained in:
TreeHugger Robot
2020-02-28 21:44:22 +00:00
committed by Android (Google) Code Review
2 changed files with 105 additions and 120 deletions

View File

@@ -22,6 +22,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.Slog;
import libcore.util.NativeAllocationRegistry;
/**
* An input channel specifies the file descriptors used to send input events to
* a window in another process. It is Parcelable so that it can be sent
@@ -33,6 +35,10 @@ public final class InputChannel implements Parcelable {
private static final String TAG = "InputChannel";
private static final boolean DEBUG = false;
private static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
InputChannel.class.getClassLoader(),
nativeGetFinalizer());
@UnsupportedAppUsage
public static final @android.annotation.NonNull Parcelable.Creator<InputChannel> CREATOR
@@ -51,18 +57,18 @@ public final class InputChannel implements Parcelable {
@SuppressWarnings("unused")
@UnsupportedAppUsage
private long mPtr; // used by native code
private Runnable mCleaner;
private static native InputChannel[] nativeOpenInputChannelPair(String name);
private static native long[] nativeOpenInputChannelPair(String name);
private native void nativeDispose(boolean finalized);
private native void nativeRelease();
private native void nativeTransferTo(InputChannel other);
private native void nativeReadFromParcel(Parcel parcel);
private native void nativeWriteToParcel(Parcel parcel);
private native void nativeDup(InputChannel target);
private native IBinder nativeGetToken();
private static native long nativeGetFinalizer();
private native void nativeDispose(long channel);
private native long nativeReadFromParcel(Parcel parcel);
private native void nativeWriteToParcel(Parcel parcel, long channel);
private native long nativeDup(long channel);
private native IBinder nativeGetToken(long channel);
private native String nativeGetName();
private native String nativeGetName(long channel);
/**
* Creates an uninitialized input channel.
@@ -73,13 +79,25 @@ public final class InputChannel implements Parcelable {
public InputChannel() {
}
@Override
protected void finalize() throws Throwable {
try {
nativeDispose(true);
} finally {
super.finalize();
/**
* Set Native input channel object from native space.
* @param nativeChannel the native channel object.
*
* @hide
*/
@UnsupportedAppUsage
public void SetNativeInputChannel(long nativeChannel) {
if (nativeChannel == 0) {
throw new IllegalArgumentException("Set native input channel to null.");
}
if (mPtr != 0) {
throw new IllegalArgumentException("Already has native input channel.");
}
if (DEBUG) {
Slog.d(TAG, "SetNativeInputChannel : " + String.format("%x", nativeChannel));
}
mCleaner = sRegistry.registerNativeAllocation(this, nativeChannel);
mPtr = nativeChannel;
}
/**
@@ -98,7 +116,13 @@ public final class InputChannel implements Parcelable {
if (DEBUG) {
Slog.d(TAG, "Opening input channel pair '" + name + "'");
}
return nativeOpenInputChannelPair(name);
InputChannel channels[] = new InputChannel[2];
long[] nativeChannels = nativeOpenInputChannelPair(name);
for (int i = 0; i< 2; i++) {
channels[i] = new InputChannel();
channels[i].SetNativeInputChannel(nativeChannels[i]);
}
return channels;
}
/**
@@ -106,7 +130,7 @@ public final class InputChannel implements Parcelable {
* @return The input channel name.
*/
public String getName() {
String name = nativeGetName();
String name = nativeGetName(mPtr);
return name != null ? name : "uninitialized";
}
@@ -116,7 +140,7 @@ public final class InputChannel implements Parcelable {
* When all references are released, the input channel will be closed.
*/
public void dispose() {
nativeDispose(false);
nativeDispose(mPtr);
}
/**
@@ -124,7 +148,6 @@ public final class InputChannel implements Parcelable {
* still exist in native-land, then the channel may continue to exist.
*/
public void release() {
nativeRelease();
}
/**
@@ -137,8 +160,10 @@ public final class InputChannel implements Parcelable {
if (outParameter == null) {
throw new IllegalArgumentException("outParameter must not be null");
}
nativeTransferTo(outParameter);
if (outParameter.mPtr != 0) {
throw new IllegalArgumentException("Other object already has a native input channel.");
}
outParameter.SetNativeInputChannel(nativeDup(mPtr));
}
/**
@@ -146,7 +171,7 @@ public final class InputChannel implements Parcelable {
*/
public InputChannel dup() {
InputChannel target = new InputChannel();
nativeDup(target);
target.SetNativeInputChannel(nativeDup(mPtr));
return target;
}
@@ -159,8 +184,10 @@ public final class InputChannel implements Parcelable {
if (in == null) {
throw new IllegalArgumentException("in must not be null");
}
nativeReadFromParcel(in);
long nativeIn = nativeReadFromParcel(in);
if (nativeIn > 0) {
SetNativeInputChannel(nativeIn);
}
}
@Override
@@ -169,7 +196,7 @@ public final class InputChannel implements Parcelable {
throw new IllegalArgumentException("out must not be null");
}
nativeWriteToParcel(out);
nativeWriteToParcel(out, mPtr);
if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0) {
dispose();
@@ -182,6 +209,6 @@ public final class InputChannel implements Parcelable {
}
public IBinder getToken() {
return nativeGetToken();
return nativeGetToken(mPtr);
}
}

View File

@@ -37,7 +37,6 @@ static struct {
jclass clazz;
jfieldID mPtr; // native object attached to the DVM InputChannel
jmethodID ctor;
} gInputChannelClassInfo;
// ----------------------------------------------------------------------------
@@ -88,12 +87,6 @@ static NativeInputChannel* android_view_InputChannel_getNativeInputChannel(JNIEn
return reinterpret_cast<NativeInputChannel*>(longPtr);
}
static void android_view_InputChannel_setNativeInputChannel(JNIEnv* env, jobject inputChannelObj,
NativeInputChannel* nativeInputChannel) {
env->SetLongField(inputChannelObj, gInputChannelClassInfo.mPtr,
reinterpret_cast<jlong>(nativeInputChannel));
}
sp<InputChannel> android_view_InputChannel_getInputChannel(JNIEnv* env, jobject inputChannelObj) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, inputChannelObj);
@@ -111,20 +104,15 @@ void android_view_InputChannel_setDisposeCallback(JNIEnv* env, jobject inputChan
}
}
static jobject android_view_InputChannel_createInputChannel(JNIEnv* env,
static jlong android_view_InputChannel_createInputChannel(JNIEnv* env,
sp<InputChannel> inputChannel) {
std::unique_ptr<NativeInputChannel> nativeInputChannel =
std::make_unique<NativeInputChannel>(inputChannel);
jobject inputChannelObj = env->NewObject(gInputChannelClassInfo.clazz,
gInputChannelClassInfo.ctor);
if (inputChannelObj) {
android_view_InputChannel_setNativeInputChannel(env, inputChannelObj,
nativeInputChannel.release());
}
return inputChannelObj;
return reinterpret_cast<jlong>(nativeInputChannel.release());
}
static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
static jlongArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
jclass clazz, jstring nameObj) {
ScopedUtfChars nameChars(env, nameObj);
std::string name = nameChars.c_str();
@@ -140,96 +128,71 @@ static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv*
return nullptr;
}
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, nullptr);
jlongArray channelPair = env->NewLongArray(2);
if (channelPair == nullptr) {
return nullptr;
}
jlong* outArray = env->GetLongArrayElements(channelPair, 0);
outArray[0] = android_view_InputChannel_createInputChannel(env, serverChannel);
if (env->ExceptionCheck()) {
return nullptr;
}
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env, serverChannel);
outArray[1] = android_view_InputChannel_createInputChannel(env, clientChannel);
if (env->ExceptionCheck()) {
return nullptr;
}
env->ReleaseLongArrayElements(channelPair, outArray, 0);
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env, clientChannel);
if (env->ExceptionCheck()) {
return nullptr;
}
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
return channelPair;
}
static void android_view_InputChannel_nativeDispose(JNIEnv* env, jobject obj, jboolean finalized) {
static void InputChannel_nativeDestroy(void *rawInputChannel) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
reinterpret_cast<NativeInputChannel *>(rawInputChannel);
if (nativeInputChannel) {
if (finalized) {
ALOGW("Input channel object '%s' was finalized without being disposed!",
nativeInputChannel->getInputChannel()->getName().c_str());
}
delete nativeInputChannel;
}
}
static jlong android_view_InputChannel_getNativeFinalizer(JNIEnv* env, jobject obj) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&InputChannel_nativeDestroy));
}
static void android_view_InputChannel_nativeDispose(JNIEnv* env, jobject obj, jlong channel) {
NativeInputChannel* nativeInputChannel =
reinterpret_cast<NativeInputChannel*>(channel);
if (nativeInputChannel) {
nativeInputChannel->invokeAndRemoveDisposeCallback(env, obj);
android_view_InputChannel_setNativeInputChannel(env, obj, nullptr);
delete nativeInputChannel;
}
}
static void android_view_InputChannel_nativeRelease(JNIEnv* env, jobject obj, jboolean finalized) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
if (nativeInputChannel) {
android_view_InputChannel_setNativeInputChannel(env, obj, nullptr);
delete nativeInputChannel;
}
}
static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,
jobject otherObj) {
if (android_view_InputChannel_getNativeInputChannel(env, otherObj) != nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Other object already has a native input channel.");
return;
}
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
android_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel);
android_view_InputChannel_setNativeInputChannel(env, obj, nullptr);
}
static void android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject obj,
static jlong android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject obj,
jobject parcelObj) {
if (android_view_InputChannel_getNativeInputChannel(env, obj) != nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"This object already has a native input channel.");
return;
}
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (parcel) {
bool isInitialized = parcel->readInt32();
if (isInitialized) {
sp<InputChannel> inputChannel = InputChannel::read(*parcel);
NativeInputChannel* nativeInputChannel = new NativeInputChannel(inputChannel);
android_view_InputChannel_setNativeInputChannel(env, obj, nativeInputChannel);
return reinterpret_cast<jlong>(nativeInputChannel);
}
}
return 0;
}
static void android_view_InputChannel_nativeWriteToParcel(JNIEnv* env, jobject obj,
jobject parcelObj) {
jobject parcelObj, jlong channel) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (parcel == nullptr) {
ALOGE("Could not obtain parcel for Java object");
return;
}
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
reinterpret_cast<NativeInputChannel*>(channel);
if (!nativeInputChannel) {
parcel->writeInt32(0); // not initialized
return;
@@ -238,9 +201,9 @@ static void android_view_InputChannel_nativeWriteToParcel(JNIEnv* env, jobject o
nativeInputChannel->getInputChannel()->write(*parcel);
}
static jstring android_view_InputChannel_nativeGetName(JNIEnv* env, jobject obj) {
static jstring android_view_InputChannel_nativeGetName(JNIEnv* env, jobject obj, jlong channel) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
reinterpret_cast<NativeInputChannel*>(channel);
if (! nativeInputChannel) {
return nullptr;
}
@@ -249,18 +212,19 @@ static jstring android_view_InputChannel_nativeGetName(JNIEnv* env, jobject obj)
return name;
}
static void android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jobject otherObj) {
static jlong android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jlong channel) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
reinterpret_cast<NativeInputChannel*>(channel);
if (nativeInputChannel == nullptr) {
jniThrowRuntimeException(env, "InputChannel has no valid NativeInputChannel");
return;
return 0;
}
sp<InputChannel> inputChannel = nativeInputChannel->getInputChannel();
if (inputChannel == nullptr) {
jniThrowRuntimeException(env, "NativeInputChannel has no corresponding InputChannel");
return;
return 0;
}
sp<InputChannel> dupInputChannel = inputChannel->dup();
if (dupInputChannel == nullptr) {
@@ -268,13 +232,12 @@ static void android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jobjec
"Could not duplicate input channel %s", inputChannel->getName().c_str());
jniThrowRuntimeException(env, message.c_str());
}
android_view_InputChannel_setNativeInputChannel(env, otherObj,
new NativeInputChannel(dupInputChannel));
return reinterpret_cast<jlong>(new NativeInputChannel(dupInputChannel));
}
static jobject android_view_InputChannel_nativeGetToken(JNIEnv* env, jobject obj) {
static jobject android_view_InputChannel_nativeGetToken(JNIEnv* env, jobject obj, jlong channel) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
reinterpret_cast<NativeInputChannel*>(channel);
if (nativeInputChannel) {
return javaObjectForIBinder(env,
nativeInputChannel->getInputChannel()->getConnectionToken());
@@ -286,23 +249,21 @@ static jobject android_view_InputChannel_nativeGetToken(JNIEnv* env, jobject obj
static const JNINativeMethod gInputChannelMethods[] = {
/* name, signature, funcPtr */
{ "nativeOpenInputChannelPair", "(Ljava/lang/String;)[Landroid/view/InputChannel;",
{ "nativeOpenInputChannelPair", "(Ljava/lang/String;)[J",
(void*)android_view_InputChannel_nativeOpenInputChannelPair },
{ "nativeDispose", "(Z)V",
{ "nativeGetFinalizer", "()J",
(void*)android_view_InputChannel_getNativeFinalizer },
{ "nativeDispose", "(J)V",
(void*)android_view_InputChannel_nativeDispose },
{ "nativeRelease", "()V",
(void*)android_view_InputChannel_nativeRelease },
{ "nativeTransferTo", "(Landroid/view/InputChannel;)V",
(void*)android_view_InputChannel_nativeTransferTo },
{ "nativeReadFromParcel", "(Landroid/os/Parcel;)V",
{ "nativeReadFromParcel", "(Landroid/os/Parcel;)J",
(void*)android_view_InputChannel_nativeReadFromParcel },
{ "nativeWriteToParcel", "(Landroid/os/Parcel;)V",
{ "nativeWriteToParcel", "(Landroid/os/Parcel;J)V",
(void*)android_view_InputChannel_nativeWriteToParcel },
{ "nativeGetName", "()Ljava/lang/String;",
{ "nativeGetName", "(J)Ljava/lang/String;",
(void*)android_view_InputChannel_nativeGetName },
{ "nativeDup", "(Landroid/view/InputChannel;)V",
{ "nativeDup", "(J)J",
(void*)android_view_InputChannel_nativeDup },
{ "nativeGetToken", "()Landroid/os/IBinder;",
{ "nativeGetToken", "(J)Landroid/os/IBinder;",
(void*)android_view_InputChannel_nativeGetToken },
};
@@ -315,9 +276,6 @@ int register_android_view_InputChannel(JNIEnv* env) {
gInputChannelClassInfo.mPtr = GetFieldIDOrDie(env, gInputChannelClassInfo.clazz, "mPtr", "J");
gInputChannelClassInfo.ctor = GetMethodIDOrDie(env, gInputChannelClassInfo.clazz, "<init>",
"()V");
return res;
}