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

Commit d8b44308 authored by Nick Chameyev's avatar Nick Chameyev Committed by Android (Google) Code Review
Browse files

Merge "Use NDK version of transaction completed callback" into 24D1-dev

parents f4655586 5ec8f4e5
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.utils.SurfaceControlUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1631,8 +1632,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        if (mTransactionCompletedListeners != null) {
            for (int i = 0; i < mTransactionCompletedListeners.size(); i++) {
                final Runnable listener = mTransactionCompletedListeners.get(i);
                transaction.addTransactionCompletedListener(Runnable::run,
                        (stats) -> listener.run());
                SurfaceControlUtils.addTransactionCompletedListener(transaction, listener);
            }
        }

+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm.utils;

import android.view.SurfaceControl;

/**
 * JNI wrapper for ASurfaceTransaction_setOnComplete NDK method which is not
 * exposed as a Java API on older Android versions
 */
public class SurfaceControlUtils {

    /**
     * Adds a listener for transaction completion (when transaction is presented on the screen)
     * @param transaction transaction to which add the listener
     * @param runnable callback which will be called when transaction is presented
     */
    public static void addTransactionCompletedListener(SurfaceControl.Transaction transaction,
            Runnable onComplete) {
        nativeAddTransactionCompletedListener(transaction, onComplete);
    }

    private static native void nativeAddTransactionCompletedListener(
        SurfaceControl.Transaction transaction, Runnable callback);
}
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ cc_library_static {
        "com_android_server_pm_PackageManagerShellCommandDataLoader.cpp",
        "com_android_server_sensor_SensorService.cpp",
        "com_android_server_wm_TaskFpsCallbackController.cpp",
        "com_android_server_wm_utils_SurfaceControlUtils.cpp",
        "onload.cpp",
        ":lib_cachedAppOptimizer_native",
        ":lib_gameManagerService_native",
+105 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "SurfaceControlUtils"

#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include <android/surface_control.h>
#include <android/surface_control_jni.h>
#include <nativehelper/JNIHelp.h>
#include <utils/Log.h>
#include <utils/RefBase.h>

#include "core_jni_helpers.h"

namespace android {

namespace {

static struct {
    jclass clazz;
    jmethodID run;
} gRunnableClassInfo;

class TransactionCompletedListenerWrapper {
public:
    explicit TransactionCompletedListenerWrapper(JNIEnv* env, jobject object) {
        env->GetJavaVM(&mVm);
        mTransactionCompletedListenerObject = env->NewGlobalRef(object);
        LOG_ALWAYS_FATAL_IF(!mTransactionCompletedListenerObject, "Failed to make global ref");
    }

    ~TransactionCompletedListenerWrapper() {
        getenv()->DeleteGlobalRef(mTransactionCompletedListenerObject);
    }

    void callback() {
        JNIEnv* env = getenv();

        env->CallVoidMethod(mTransactionCompletedListenerObject, gRunnableClassInfo.run);

        DieIfException(env, "Uncaught exception in TransactionCompletedListener.");
    }

    static void transactionCallbackThunk(void* context, ASurfaceTransactionStats* stats) {
        TransactionCompletedListenerWrapper* listener =
                reinterpret_cast<TransactionCompletedListenerWrapper*>(context);
        listener->callback();
        delete listener;
    }

private:
    jobject mTransactionCompletedListenerObject;
    JavaVM* mVm;

    JNIEnv* getenv() {
        JNIEnv* env;
        mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
        return env;
    }
};

static void nativeAddTransactionCompletedListener(JNIEnv* env, jclass clazz,
                                                  jobject transactionObj,
                                                  jobject transactionCompletedListener) {
    ASurfaceTransaction* transaction = ASurfaceTransaction_fromJava(env, transactionObj);
    auto context = new TransactionCompletedListenerWrapper(env, transactionCompletedListener);
    ASurfaceTransaction_setOnComplete(transaction, reinterpret_cast<void*>(context),
                                      TransactionCompletedListenerWrapper::
                                                         transactionCallbackThunk);
}

static const JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        {"nativeAddTransactionCompletedListener",
        "(Landroid/view/SurfaceControl$Transaction;Ljava/lang/Runnable;)V",
        (void*) nativeAddTransactionCompletedListener}};
} // namespace

int register_com_android_server_wm_utils_SurfaceControlUtils(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env, "com/android/server/wm/utils/SurfaceControlUtils",
                                       gMethods, NELEM(gMethods));
    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");

    jclass runnableClazz = FindClassOrDie(env, "java/lang/Runnable");
    gRunnableClassInfo.clazz = MakeGlobalRefOrDie(env, runnableClazz);
    gRunnableClassInfo.run = GetMethodIDOrDie(env, runnableClazz, "run", "()V");

    return 0;
}

} // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env);
int register_android_server_companion_virtual_InputController(JNIEnv* env);
int register_android_server_app_GameManagerService(JNIEnv* env);
int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
int register_com_android_server_wm_utils_SurfaceControlUtils(JNIEnv* env);
int register_com_android_server_display_DisplayControl(JNIEnv* env);
int register_com_android_server_SystemClockTime(JNIEnv* env);
int register_android_server_display_smallAreaDetectionController(JNIEnv* env);
@@ -130,6 +131,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
    register_android_server_companion_virtual_InputController(env);
    register_android_server_app_GameManagerService(env);
    register_com_android_server_wm_TaskFpsCallbackController(env);
    register_com_android_server_wm_utils_SurfaceControlUtils(env);
    register_com_android_server_display_DisplayControl(env);
    register_com_android_server_SystemClockTime(env);
    register_android_server_display_smallAreaDetectionController(env);