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

Commit a61301c4 authored by Patrick Williams's avatar Patrick Williams
Browse files

Add stalled transaction message to input ANRs

Bug: 287577707
Test: presubmit
Change-Id: I569465d22174090ce524bad9ef950075d868fac8
Merged-In: I569465d22174090ce524bad9ef950075d868fac8
parent 97c61a08
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.gui.DropInputMode;
import android.gui.StalledTransactionInfo;
import android.hardware.DataSpace;
import android.hardware.HardwareBuffer;
import android.hardware.OverlayProperties;
@@ -292,6 +293,7 @@ public final class SurfaceControl implements Parcelable {
            long nativeObject, long nativeTpc, TrustedPresentationThresholds thresholds);
    private static native void nativeClearTrustedPresentationCallback(long transactionObj,
            long nativeObject);
    private static native StalledTransactionInfo nativeGetStalledTransactionInfo(int pid);

    /**
     * Transforms that can be applied to buffers as they are displayed to a window.
@@ -4363,4 +4365,11 @@ public final class SurfaceControl implements Parcelable {
        callback.accept(fence);
    }

    /**
     * @hide
     */
    public static StalledTransactionInfo getStalledTransactionInfo(int pid) {
        return nativeGetStalledTransactionInfo(pid);
    }

}
+45 −0
Original line number Diff line number Diff line
@@ -257,6 +257,14 @@ static struct {
    jmethodID onTrustedPresentationChanged;
} gTrustedPresentationCallbackClassInfo;

static struct {
    jclass clazz;
    jmethodID ctor;
    jfieldID layerName;
    jfieldID bufferId;
    jfieldID frameNumber;
} gStalledTransactionInfoClassInfo;

constexpr ui::Dataspace pickDataspaceFromColorMode(const ui::ColorMode colorMode) {
    switch (colorMode) {
        case ui::ColorMode::DISPLAY_P3:
@@ -2032,6 +2040,29 @@ static jlong getNativeTrustedPresentationCallbackFinalizer(JNIEnv* env, jclass c
    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeTpc));
}

static jobject nativeGetStalledTransactionInfo(JNIEnv* env, jclass clazz, jint pid) {
    std::optional<gui::StalledTransactionInfo> stalledTransactionInfo =
            SurfaceComposerClient::getStalledTransactionInfo(pid);
    if (!stalledTransactionInfo) {
        return nullptr;
    }

    jobject jStalledTransactionInfo = env->NewObject(gStalledTransactionInfoClassInfo.clazz,
                                                     gStalledTransactionInfoClassInfo.ctor);
    if (!jStalledTransactionInfo) {
        jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
        return nullptr;
    }

    env->SetObjectField(jStalledTransactionInfo, gStalledTransactionInfoClassInfo.layerName,
                        env->NewStringUTF(String8{stalledTransactionInfo->layerName}));
    env->SetLongField(jStalledTransactionInfo, gStalledTransactionInfoClassInfo.bufferId,
                      static_cast<jlong>(stalledTransactionInfo->bufferId));
    env->SetLongField(jStalledTransactionInfo, gStalledTransactionInfoClassInfo.frameNumber,
                      static_cast<jlong>(stalledTransactionInfo->frameNumber));
    return jStalledTransactionInfo;
}

// ----------------------------------------------------------------------------

SurfaceControl* android_view_SurfaceControl_getNativeSurfaceControl(JNIEnv* env,
@@ -2281,6 +2312,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
    {"nativeCreateTpc", "(Landroid/view/SurfaceControl$TrustedPresentationCallback;)J",
            (void*)nativeCreateTpc},
    {"getNativeTrustedPresentationCallbackFinalizer", "()J", (void*)getNativeTrustedPresentationCallbackFinalizer },
    {"nativeGetStalledTransactionInfo", "(I)Landroid/gui/StalledTransactionInfo;",
            (void*) nativeGetStalledTransactionInfo },
        // clang-format on
};

@@ -2524,6 +2557,18 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    gTrustedPresentationCallbackClassInfo.onTrustedPresentationChanged =
            GetMethodIDOrDie(env, trustedPresentationCallbackClazz, "onTrustedPresentationChanged",
                             "(Z)V");

    jclass stalledTransactionInfoClazz = FindClassOrDie(env, "android/gui/StalledTransactionInfo");
    gStalledTransactionInfoClassInfo.clazz = MakeGlobalRefOrDie(env, stalledTransactionInfoClazz);
    gStalledTransactionInfoClassInfo.ctor =
            GetMethodIDOrDie(env, stalledTransactionInfoClazz, "<init>", "()V");
    gStalledTransactionInfoClassInfo.layerName =
            GetFieldIDOrDie(env, stalledTransactionInfoClazz, "layerName", "Ljava/lang/String;");
    gStalledTransactionInfoClassInfo.bufferId =
            GetFieldIDOrDie(env, stalledTransactionInfoClazz, "bufferId", "J");
    gStalledTransactionInfoClassInfo.frameNumber =
            GetFieldIDOrDie(env, stalledTransactionInfoClazz, "frameNumber", "J");

    return err;
}

+17 −6
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.server.wm.WindowManagerService.H.ON_POINTER_DOWN_OUTSI

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.gui.StalledTransactionInfo;
import android.os.Debug;
import android.os.IBinder;
import android.util.Slog;
@@ -96,7 +97,7 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
    @Override
    public void notifyNoFocusedWindowAnr(@NonNull InputApplicationHandle applicationHandle) {
        TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchNoFocusedWindow(
                timeoutMessage("Application does not have a focused window"));
                timeoutMessage(OptionalInt.empty(), "Application does not have a focused window"));
        mService.mAnrController.notifyAppUnresponsive(applicationHandle, timeoutRecord);
    }

@@ -104,7 +105,7 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
    public void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
            String reason) {
        TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchWindowUnresponsive(
                timeoutMessage(reason));
                timeoutMessage(pid, reason));
        mService.mAnrController.notifyWindowUnresponsive(token, pid, timeoutRecord);
    }

@@ -354,11 +355,21 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
        mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
    }

    private String timeoutMessage(String reason) {
        if (reason == null) {
            return "Input dispatching timed out";
    private String timeoutMessage(OptionalInt pid, String reason) {
        String message = (reason == null) ? "Input dispatching timed out."
                : String.format("Input dispatching timed out (%s).", reason);
        if (pid.isEmpty()) {
            return message;
        }
        return "Input dispatching timed out (" + reason + ")";
        StalledTransactionInfo stalledTransactionInfo =
                SurfaceControl.getStalledTransactionInfo(pid.getAsInt());
        if (stalledTransactionInfo == null) {
            return message;
        }
        return String.format("%s Buffer processing for the associated surface is stuck due to an "
                + "unsignaled fence (window=%s, bufferId=0x%016X, frameNumber=%s). This "
                + "potentially indicates a GPU hang.", message, stalledTransactionInfo.layerName,
                stalledTransactionInfo.bufferId, stalledTransactionInfo.frameNumber);
    }

    void dump(PrintWriter pw, String prefix) {