Skip to content

Commit

Permalink
Reland "Listen for Vsync callback on the UI thread directly" (flutter…
Browse files Browse the repository at this point in the history
  • Loading branch information
ColdPaleLight authored Feb 24, 2022
1 parent e50d865 commit a67a366
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 24 deletions.
69 changes: 56 additions & 13 deletions fml/platform/android/message_loop_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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) {
Expand All @@ -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
4 changes: 4 additions & 0 deletions fml/platform/android/message_loop_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,10 @@ public void setRefreshRateFPS(float refreshRateFPS) {

/**
* 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.
*/
Expand All @@ -272,7 +273,7 @@ public void setAsyncWaitForVsyncDelegate(@Nullable AsyncWaitForVsyncDelegate del
}

// 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);
Expand Down
5 changes: 5 additions & 0 deletions shell/platform/android/library_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
12 changes: 5 additions & 7 deletions shell/platform/android/vsync_waiter_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a67a366

Please sign in to comment.