mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reland "Listen for Vsync callback on the UI thread directly" (flutter/engine#31494)
This commit is contained in:
parent
c101941c37
commit
1a179ecff2
@ -13,6 +13,31 @@ namespace fml {
|
||||
|
||||
static constexpr int kClockType = CLOCK_MONOTONIC;
|
||||
|
||||
static fml::jni::ScopedJavaGlobalRef<jclass>* g_looper_class = nullptr;
|
||||
static jmethodID g_looper_prepare_method_ = nullptr;
|
||||
static jmethodID g_looper_loop_method_ = nullptr;
|
||||
static jmethodID g_looper_my_looper_method_ = nullptr;
|
||||
static jmethodID g_looper_quit_method_ = nullptr;
|
||||
|
||||
static void LooperPrepare() {
|
||||
JNIEnv* env = fml::jni::AttachCurrentThread();
|
||||
env->CallStaticVoidMethod(g_looper_class->obj(), g_looper_prepare_method_);
|
||||
}
|
||||
|
||||
static void LooperLoop() {
|
||||
JNIEnv* env = fml::jni::AttachCurrentThread();
|
||||
env->CallStaticVoidMethod(g_looper_class->obj(), g_looper_loop_method_);
|
||||
}
|
||||
|
||||
static void LooperQuit() {
|
||||
JNIEnv* env = fml::jni::AttachCurrentThread();
|
||||
auto my_looper = env->CallStaticObjectMethod(g_looper_class->obj(),
|
||||
g_looper_my_looper_method_);
|
||||
if (my_looper != nullptr) {
|
||||
env->CallVoidMethod(my_looper, g_looper_quit_method_);
|
||||
}
|
||||
}
|
||||
|
||||
static ALooper* AcquireLooperForThread() {
|
||||
ALooper* looper = ALooper_forThread();
|
||||
|
||||
@ -63,23 +88,15 @@ void MessageLoopAndroid::Run() {
|
||||
FML_DCHECK(looper_.get() == ALooper_forThread());
|
||||
|
||||
running_ = true;
|
||||
|
||||
while (running_) {
|
||||
int result = ::ALooper_pollOnce(-1, // infinite timeout
|
||||
nullptr, // out fd,
|
||||
nullptr, // out events,
|
||||
nullptr // out data
|
||||
);
|
||||
if (result == ALOOPER_POLL_TIMEOUT || result == ALOOPER_POLL_ERROR) {
|
||||
// This handles the case where the loop is terminated using ALooper APIs.
|
||||
running_ = false;
|
||||
}
|
||||
}
|
||||
// Initialize the current thread as a looper.
|
||||
LooperPrepare();
|
||||
// Run the message queue in this thread.
|
||||
LooperLoop();
|
||||
}
|
||||
|
||||
void MessageLoopAndroid::Terminate() {
|
||||
running_ = false;
|
||||
ALooper_wake(looper_.get());
|
||||
LooperQuit();
|
||||
}
|
||||
|
||||
void MessageLoopAndroid::WakeUp(fml::TimePoint time_point) {
|
||||
@ -93,4 +110,30 @@ void MessageLoopAndroid::OnEventFired() {
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageLoopAndroid::Register(JNIEnv* env) {
|
||||
jclass clazz = env->FindClass("android/os/Looper");
|
||||
FML_CHECK(clazz != nullptr);
|
||||
|
||||
g_looper_class = new fml::jni::ScopedJavaGlobalRef<jclass>(env, clazz);
|
||||
FML_CHECK(!g_looper_class->is_null());
|
||||
|
||||
g_looper_prepare_method_ =
|
||||
env->GetStaticMethodID(g_looper_class->obj(), "prepare", "()V");
|
||||
FML_CHECK(g_looper_prepare_method_ != nullptr);
|
||||
|
||||
g_looper_loop_method_ =
|
||||
env->GetStaticMethodID(g_looper_class->obj(), "loop", "()V");
|
||||
FML_CHECK(g_looper_loop_method_ != nullptr);
|
||||
|
||||
g_looper_my_looper_method_ = env->GetStaticMethodID(
|
||||
g_looper_class->obj(), "myLooper", "()Landroid/os/Looper;");
|
||||
FML_CHECK(g_looper_my_looper_method_ != nullptr);
|
||||
|
||||
g_looper_quit_method_ =
|
||||
env->GetMethodID(g_looper_class->obj(), "quit", "()V");
|
||||
FML_CHECK(g_looper_quit_method_ != nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace fml
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/fml/message_loop_impl.h"
|
||||
#include "flutter/fml/platform/android/jni_util.h"
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
|
||||
namespace fml {
|
||||
@ -26,6 +27,9 @@ struct UniqueLooperTraits {
|
||||
/// This implemenation wraps usage of Android's \p looper.
|
||||
/// \see https://developer.android.com/ndk/reference/group/looper
|
||||
class MessageLoopAndroid : public MessageLoopImpl {
|
||||
public:
|
||||
static bool Register(JNIEnv* env);
|
||||
|
||||
private:
|
||||
fml::UniqueObject<ALooper*, UniqueLooperTraits> looper_;
|
||||
fml::UniqueFD timer_fd_;
|
||||
|
||||
@ -261,9 +261,10 @@ public class FlutterJNI {
|
||||
|
||||
/**
|
||||
* The Android vsync waiter implementation in C++ needs to know when a vsync signal arrives, which
|
||||
* is obtained via Java API. The delegate set here is called on the C++ side when the engine is
|
||||
* ready to wait for the next vsync signal. The delegate is expected to add a postFrameCallback to
|
||||
* the {@link android.view.Choreographer}, and call {@link onVsync} to notify the engine.
|
||||
* is obtained via Java API. The delegate set here is called on the C++ side on the ui thread when
|
||||
* the engine is ready to wait for the next vsync signal. The delegate is expected to add a
|
||||
* postFrameCallback to the {@link android.view.Choreographer}, and call {@link onVsync} to notify
|
||||
* the engine.
|
||||
*
|
||||
* @param delegate The delegate that will call the engine back on the next vsync signal.
|
||||
*/
|
||||
@ -272,7 +273,7 @@ public class FlutterJNI {
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): add javadocs
|
||||
// Called by native.
|
||||
// Called by native on the ui thread.
|
||||
private static void asyncWaitForVsync(final long cookie) {
|
||||
if (asyncWaitForVsyncDelegate != null) {
|
||||
asyncWaitForVsyncDelegate.asyncWaitForVsync(cookie);
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/fml/platform/android/jni_util.h"
|
||||
#include "flutter/fml/platform/android/message_loop_android.h"
|
||||
#include "flutter/shell/platform/android/android_image_generator.h"
|
||||
#include "flutter/shell/platform/android/flutter_main.h"
|
||||
#include "flutter/shell/platform/android/platform_view_android.h"
|
||||
@ -32,5 +33,9 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
result = flutter::AndroidImageGenerator::Register(env);
|
||||
FML_CHECK(result);
|
||||
|
||||
// Register MessageLoopAndroid.
|
||||
result = fml::MessageLoopAndroid::Register(env);
|
||||
FML_CHECK(result);
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
@ -29,13 +29,11 @@ void VsyncWaiterAndroid::AwaitVSync() {
|
||||
auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
|
||||
jlong java_baton = reinterpret_cast<jlong>(weak_this);
|
||||
|
||||
task_runners_.GetPlatformTaskRunner()->PostTask([java_baton]() {
|
||||
JNIEnv* env = fml::jni::AttachCurrentThread();
|
||||
env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), //
|
||||
g_async_wait_for_vsync_method_, //
|
||||
java_baton //
|
||||
);
|
||||
});
|
||||
JNIEnv* env = fml::jni::AttachCurrentThread();
|
||||
env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), //
|
||||
g_async_wait_for_vsync_method_, //
|
||||
java_baton //
|
||||
);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user