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

Commit 57558eca authored by arthurhung's avatar arthurhung
Browse files

Fix gesture input monitor dispose

The gesture input monitor is to detect system gesture when user swipe on
the navigation bar or the edge, that should be unregistered after
the process (ex. launcher) is killed.

This could solve two problems:
1. InputChannel.dispose function didn't clear the native InputChannel
   reference until the 'finalize' function called, clear it in dispose.
2. We use a Bundle object to communicate systemui and launcher, but the
   PARCELABLE_WRITE_RETURN_VALUE flag can't be applied when write the
   parcelable value, change InputMonitorCompat to implement Parceable and
   apply flag when return via binder call.

Bug: 142581626
Test: kill launcher process, dumpsys input
Change-Id: Iaff774e96c58f00a26b7bedb809a0fb951862786
parent ff962aaf
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ public:
    inline sp<InputChannel> getInputChannel() { return mInputChannel; }

    void setDisposeCallback(InputChannelObjDisposeCallback callback, void* data);
    void invokeAndRemoveDisposeCallback(JNIEnv* env, jobject obj);
    void dispose(JNIEnv* env, jobject obj);

private:
    sp<InputChannel> mInputChannel;
@@ -71,12 +71,17 @@ void NativeInputChannel::setDisposeCallback(InputChannelObjDisposeCallback callb
    mDisposeData = data;
}

void NativeInputChannel::invokeAndRemoveDisposeCallback(JNIEnv* env, jobject obj) {
void NativeInputChannel::dispose(JNIEnv* env, jobject obj) {
    if (!mInputChannel) {
        return;
    }

    if (mDisposeCallback) {
        mDisposeCallback(env, obj, mInputChannel, mDisposeData);
        mDisposeCallback = nullptr;
        mDisposeData = nullptr;
    }
    mInputChannel.clear();
}

// ----------------------------------------------------------------------------
@@ -97,7 +102,7 @@ void android_view_InputChannel_setDisposeCallback(JNIEnv* env, jobject inputChan
        InputChannelObjDisposeCallback callback, void* data) {
    NativeInputChannel* nativeInputChannel =
            android_view_InputChannel_getNativeInputChannel(env, inputChannelObj);
    if (nativeInputChannel == nullptr) {
    if (!nativeInputChannel || !nativeInputChannel->getInputChannel()) {
        ALOGW("Cannot set dispose callback because input channel object has not been initialized.");
    } else {
        nativeInputChannel->setDisposeCallback(callback, data);
@@ -165,7 +170,7 @@ static void android_view_InputChannel_nativeDispose(JNIEnv* env, jobject obj, jl
            reinterpret_cast<NativeInputChannel*>(channel);

    if (nativeInputChannel) {
        nativeInputChannel->invokeAndRemoveDisposeCallback(env, obj);
        nativeInputChannel->dispose(env, obj);
    }
}

@@ -193,7 +198,7 @@ static void android_view_InputChannel_nativeWriteToParcel(JNIEnv* env, jobject o
    NativeInputChannel* nativeInputChannel =
                reinterpret_cast<NativeInputChannel*>(channel);

    if (!nativeInputChannel) {
    if (!nativeInputChannel || !nativeInputChannel->getInputChannel()) {
        parcel->writeInt32(0); // not initialized
        return;
    }
@@ -204,7 +209,7 @@ static void android_view_InputChannel_nativeWriteToParcel(JNIEnv* env, jobject o
static jstring android_view_InputChannel_nativeGetName(JNIEnv* env, jobject obj, jlong channel) {
    NativeInputChannel* nativeInputChannel =
                reinterpret_cast<NativeInputChannel*>(channel);
    if (! nativeInputChannel) {
    if (!nativeInputChannel || !nativeInputChannel->getInputChannel()) {
        return nullptr;
    }

@@ -226,6 +231,7 @@ static jlong android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jlong
        jniThrowRuntimeException(env, "NativeInputChannel has no corresponding InputChannel");
        return 0;
    }

    sp<InputChannel> dupInputChannel = inputChannel->dup();
    if (dupInputChannel == nullptr) {
        std::string message = android::base::StringPrintf(
@@ -238,7 +244,7 @@ static jlong android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jlong
static jobject android_view_InputChannel_nativeGetToken(JNIEnv* env, jobject obj, jlong channel) {
    NativeInputChannel* nativeInputChannel =
                reinterpret_cast<NativeInputChannel*>(channel);
    if (nativeInputChannel) {
    if (nativeInputChannel && nativeInputChannel->getInputChannel()) {
        return javaObjectForIBinder(env,
                nativeInputChannel->getInputChannel()->getConnectionToken());
    }
+42 −3
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ package com.android.systemui.shared.system;

import android.os.Bundle;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.Choreographer;
import android.view.InputMonitor;

@@ -26,9 +28,9 @@ import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
/**
 * @see android.view.InputMonitor
 */
public class InputMonitorCompat {

public class InputMonitorCompat implements Parcelable {
    private final InputMonitor mInputMonitor;
    private boolean mForReturn = false;

    private InputMonitorCompat(InputMonitor monitor) {
        mInputMonitor = monitor;
@@ -61,6 +63,43 @@ public class InputMonitorCompat {
     * Gets the input monitor stored in a bundle
     */
    public static InputMonitorCompat fromBundle(Bundle bundle, String key) {
        return new InputMonitorCompat((InputMonitor) bundle.getParcelable(key));
        bundle.setClassLoader(InputMonitorCompat.class.getClassLoader());
        return (InputMonitorCompat) bundle.getParcelable(key);
    }

    /**
     * Gets the input monitor compat as the return value.
     */
    public static InputMonitorCompat obtainReturnValue(InputMonitor monitor) {
        final InputMonitorCompat monitorCompat = new InputMonitorCompat(monitor);
        monitorCompat.mForReturn = true;
        return monitorCompat;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        mInputMonitor.writeToParcel(dest,
                mForReturn ? PARCELABLE_WRITE_RETURN_VALUE : flags);
    }

    private InputMonitorCompat(Parcel in) {
        mInputMonitor = InputMonitor.CREATOR.createFromParcel(in);
    }

    public static final Creator<InputMonitorCompat> CREATOR = new Creator<InputMonitorCompat>() {
        @Override
        public InputMonitorCompat createFromParcel(Parcel in) {
            return new InputMonitorCompat(in);
        }

        @Override
        public InputMonitorCompat[] newArray(int size) {
            return new InputMonitorCompat[size];
        }
    };
}
+5 −3
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
@@ -327,10 +328,11 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
            }
            long token = Binder.clearCallingIdentity();
            try {
                InputMonitor monitor =
                final InputMonitor monitor =
                        InputManager.getInstance().monitorGestureInput(name, displayId);
                Bundle result = new Bundle();
                result.putParcelable(KEY_EXTRA_INPUT_MONITOR, monitor);
                final Bundle result = new Bundle();
                result.putParcelable(KEY_EXTRA_INPUT_MONITOR,
                        InputMonitorCompat.obtainReturnValue(monitor));
                return result;
            } finally {
                Binder.restoreCallingIdentity(token);