diff options
| author | 2024-04-17 17:21:53 +0000 | |
|---|---|---|
| committer | 2024-04-18 13:20:23 +0000 | |
| commit | 5ec8f4e5aeca9fe4055631d0e35c3ca4fd941d4c (patch) | |
| tree | 93b206c0d7e7907fd32b1d06652bc6f9e49a37da | |
| parent | bab84f3277a017b25dfdd12f7688b961a8e32cd0 (diff) | |
Use NDK version of transaction completed callback
The addTransactionCompletedListener doesn't work
on 24D1-dev branch, it requires API flag that
is enabled only in V.
There is an NDK version of the same method
that is available since API 29 but it is not
exposed to Java. Replaced Java call to
addTransactionCompletedListener with an NDK
call to ASurfaceTransaction_setOnComplete.
Bug: 334873960
Test: fold/unfold without delay on 24D1-dev
Test: atest UnfoldToLauncherMicrobenchmark
Merged-In: Ibed2cf715cc3898167cab02e21405bf028ca1111
Change-Id: Id6dfd4615343ed524582eb62aa24dd3e0a1413b5
5 files changed, 149 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index d30ddcaba343..3f795a616fcd 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -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); } } diff --git a/services/core/java/com/android/server/wm/utils/SurfaceControlUtils.java b/services/core/java/com/android/server/wm/utils/SurfaceControlUtils.java new file mode 100644 index 000000000000..e658cc9fd766 --- /dev/null +++ b/services/core/java/com/android/server/wm/utils/SurfaceControlUtils.java @@ -0,0 +1,39 @@ +/* + * 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); +} diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 3607dddc66d5..a348d582aafa 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -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", diff --git a/services/core/jni/com_android_server_wm_utils_SurfaceControlUtils.cpp b/services/core/jni/com_android_server_wm_utils_SurfaceControlUtils.cpp new file mode 100644 index 000000000000..d29b3967eeb7 --- /dev/null +++ b/services/core/jni/com_android_server_wm_utils_SurfaceControlUtils.cpp @@ -0,0 +1,105 @@ +/* + * 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 diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 0936888b24a0..dbca8d1df1f1 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -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); |