Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 195db0db authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents 8e07c4f4 b8bf78a7
Loading
Loading
Loading
Loading
+53 −26
Original line number Diff line number Diff line
@@ -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);
    }
}
+45 −87
Original line number Diff line number Diff line
@@ -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);
    if (env->ExceptionCheck()) {
    jlongArray channelPair = env->NewLongArray(2);
    if (channelPair == nullptr) {
        return nullptr;
    }

    jobject serverChannelObj = android_view_InputChannel_createInputChannel(env, serverChannel);
    jlong* outArray = env->GetLongArrayElements(channelPair, 0);
    outArray[0] = android_view_InputChannel_createInputChannel(env, serverChannel);
    if (env->ExceptionCheck()) {
        return nullptr;
    }

    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env, clientChannel);
    outArray[1] = android_view_InputChannel_createInputChannel(env, clientChannel);
    if (env->ExceptionCheck()) {
        return nullptr;
    }
    env->ReleaseLongArrayElements(channelPair, outArray, 0);

    env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
    env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
    return channelPair;
}

static void android_view_InputChannel_nativeDispose(JNIEnv* env, jobject obj, jboolean finalized) {
    NativeInputChannel* nativeInputChannel =
            android_view_InputChannel_getNativeInputChannel(env, obj);
    if (nativeInputChannel) {
        if (finalized) {
            ALOGW("Input channel object '%s' was finalized without being disposed!",
                    nativeInputChannel->getInputChannel()->getName().c_str());
        }

        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) {
static void InputChannel_nativeDestroy(void *rawInputChannel) {
    NativeInputChannel* nativeInputChannel =
            android_view_InputChannel_getNativeInputChannel(env, obj);
            reinterpret_cast<NativeInputChannel *>(rawInputChannel);
    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;
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 =
            android_view_InputChannel_getNativeInputChannel(env, obj);
    android_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel);
    android_view_InputChannel_setNativeInputChannel(env, obj, nullptr);
}
            reinterpret_cast<NativeInputChannel*>(channel);

static void 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;
    if (nativeInputChannel) {
        nativeInputChannel->invokeAndRemoveDisposeCallback(env, obj);
    }
}

static jlong android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject obj,
        jobject parcelObj) {
    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;
}