diff --git a/fml/platform/android/message_loop_android.cc b/fml/platform/android/message_loop_android.cc index 79a59ba25032d..b4c5982181a54 100644 --- a/fml/platform/android/message_loop_android.cc +++ b/fml/platform/android/message_loop_android.cc @@ -13,31 +13,6 @@ namespace fml { static constexpr int kClockType = CLOCK_MONOTONIC; -static fml::jni::ScopedJavaGlobalRef* 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(); @@ -88,15 +63,23 @@ void MessageLoopAndroid::Run() { FML_DCHECK(looper_.get() == ALooper_forThread()); running_ = true; - // Initialize the current thread as a looper. - LooperPrepare(); - // Run the message queue in this thread. - LooperLoop(); + + 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; + } + } } void MessageLoopAndroid::Terminate() { running_ = false; - LooperQuit(); + ALooper_wake(looper_.get()); } void MessageLoopAndroid::WakeUp(fml::TimePoint time_point) { @@ -110,30 +93,4 @@ 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(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 diff --git a/fml/platform/android/message_loop_android.h b/fml/platform/android/message_loop_android.h index d1af3b9352be1..6ff26be0fd373 100644 --- a/fml/platform/android/message_loop_android.h +++ b/fml/platform/android/message_loop_android.h @@ -11,7 +11,6 @@ #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 { @@ -27,9 +26,6 @@ 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 looper_; fml::UniqueFD timer_fd_; diff --git a/lib/ui/painting/fragment_program.cc b/lib/ui/painting/fragment_program.cc index 12a1824d0b8f7..9156302789ea8 100644 --- a/lib/ui/painting/fragment_program.cc +++ b/lib/ui/painting/fragment_program.cc @@ -55,7 +55,7 @@ void FragmentProgram::init(std::string sksl, bool debugPrintSksl) { fml::RefPtr FragmentProgram::shader( Dart_Handle shader, - const tonic::Float32List& uniforms, + tonic::Float32List& uniforms, Dart_Handle samplers) { auto sampler_shaders = tonic::DartConverter>::FromDart(samplers); @@ -69,6 +69,7 @@ fml::RefPtr FragmentProgram::shader( for (size_t i = 0; i < uniform_count; i++) { uniform_floats[i] = uniforms[i]; } + uniforms.Release(); std::vector> sk_samplers(sampler_shaders.size()); for (size_t i = 0; i < sampler_shaders.size(); i++) { ImageShader* image_shader = sampler_shaders[i]; diff --git a/lib/ui/painting/fragment_program.h b/lib/ui/painting/fragment_program.h index 06cf429b32e42..a1b518a3b8168 100644 --- a/lib/ui/painting/fragment_program.h +++ b/lib/ui/painting/fragment_program.h @@ -31,7 +31,7 @@ class FragmentProgram : public RefCountedDartWrappable { void init(std::string sksl, bool debugPrintSksl); fml::RefPtr shader(Dart_Handle shader, - const tonic::Float32List& uniforms, + tonic::Float32List& uniforms, Dart_Handle samplers); static void RegisterNatives(tonic::DartLibraryNatives* natives); diff --git a/lib/ui/painting/path.cc b/lib/ui/painting/path.cc index 223f3058b5506..be9762dd7e44a 100644 --- a/lib/ui/painting/path.cc +++ b/lib/ui/painting/path.cc @@ -253,16 +253,17 @@ void CanvasPath::addPathWithMatrix(CanvasPath* path, double dy, tonic::Float64List& matrix4) { if (!path) { + matrix4.Release(); Dart_ThrowException( ToDart("Path.addPathWithMatrix called with non-genuine Path.")); return; } SkMatrix matrix = ToSkMatrix(matrix4); + matrix4.Release(); matrix.setTranslateX(matrix.getTranslateX() + dx); matrix.setTranslateY(matrix.getTranslateY() + dy); mutable_path().addPath(path->path(), matrix, SkPath::kAppend_AddPathMode); - matrix4.Release(); resetVolatility(); } @@ -281,16 +282,17 @@ void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, double dy, tonic::Float64List& matrix4) { if (!path) { + matrix4.Release(); Dart_ThrowException( ToDart("Path.addPathWithMatrix called with non-genuine Path.")); return; } SkMatrix matrix = ToSkMatrix(matrix4); + matrix4.Release(); matrix.setTranslateX(matrix.getTranslateX() + dx); matrix.setTranslateY(matrix.getTranslateY() + dy); mutable_path().addPath(path->path(), matrix, SkPath::kExtend_AddPathMode); - matrix4.Release(); resetVolatility(); } @@ -317,10 +319,11 @@ void CanvasPath::shift(Dart_Handle path_handle, double dx, double dy) { void CanvasPath::transform(Dart_Handle path_handle, tonic::Float64List& matrix4) { + auto sk_matrix = ToSkMatrix(matrix4); + matrix4.Release(); fml::RefPtr path = CanvasPath::Create(path_handle); auto& other_mutable_path = path->mutable_path(); - mutable_path().transform(ToSkMatrix(matrix4), &other_mutable_path); - matrix4.Release(); + mutable_path().transform(sk_matrix, &other_mutable_path); } tonic::Float32List CanvasPath::getBounds() { diff --git a/lib/ui/painting/vertices.cc b/lib/ui/painting/vertices.cc index 8617aee51f554..9b73939a70b2d 100644 --- a/lib/ui/painting/vertices.cc +++ b/lib/ui/painting/vertices.cc @@ -45,10 +45,10 @@ void Vertices::RegisterNatives(tonic::DartLibraryNatives* natives) { bool Vertices::init(Dart_Handle vertices_handle, SkVertices::VertexMode vertex_mode, - const tonic::Float32List& positions, - const tonic::Float32List& texture_coordinates, - const tonic::Int32List& colors, - const tonic::Uint16List& indices) { + tonic::Float32List& positions, + tonic::Float32List& texture_coordinates, + tonic::Int32List& colors, + tonic::Uint16List& indices) { UIDartState::ThrowIfUIOperationsProhibited(); uint32_t builderFlags = 0; if (texture_coordinates.data()) { @@ -76,6 +76,7 @@ bool Vertices::init(Dart_Handle vertices_handle, FML_DCHECK(positions.num_elements() == texture_coordinates.num_elements()); DecodePoints(texture_coordinates, builder.texCoords()); } + if (colors.data()) { // SkVertices::Builder assumes equal numbers of elements FML_DCHECK(positions.num_elements() / 2 == colors.num_elements()); @@ -87,6 +88,11 @@ bool Vertices::init(Dart_Handle vertices_handle, builder.indices()); } + positions.Release(); + texture_coordinates.Release(); + colors.Release(); + indices.Release(); + auto vertices = fml::MakeRefCounted(); vertices->vertices_ = builder.detach(); vertices->AssociateWithDartWrapper(vertices_handle); diff --git a/lib/ui/painting/vertices.h b/lib/ui/painting/vertices.h index 1b4c8601df806..0a6555be9ae84 100644 --- a/lib/ui/painting/vertices.h +++ b/lib/ui/painting/vertices.h @@ -26,10 +26,10 @@ class Vertices : public RefCountedDartWrappable { static bool init(Dart_Handle vertices_handle, SkVertices::VertexMode vertex_mode, - const tonic::Float32List& positions, - const tonic::Float32List& texture_coordinates, - const tonic::Int32List& colors, - const tonic::Uint16List& indices); + tonic::Float32List& positions, + tonic::Float32List& texture_coordinates, + tonic::Int32List& colors, + tonic::Uint16List& indices); const sk_sp& vertices() const { return vertices_; } diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 41230ac273573..128eb5c6a8e8d 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -261,10 +261,9 @@ 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 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. + * 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. * * @param delegate The delegate that will call the engine back on the next vsync signal. */ @@ -273,7 +272,7 @@ public void setAsyncWaitForVsyncDelegate(@Nullable AsyncWaitForVsyncDelegate del } // TODO(mattcarroll): add javadocs - // Called by native on the ui thread. + // Called by native. private static void asyncWaitForVsync(final long cookie) { if (asyncWaitForVsyncDelegate != null) { asyncWaitForVsyncDelegate.asyncWaitForVsync(cookie); diff --git a/shell/platform/android/library_loader.cc b/shell/platform/android/library_loader.cc index 5a4d444da7309..644bd5de3b8ec 100644 --- a/shell/platform/android/library_loader.cc +++ b/shell/platform/android/library_loader.cc @@ -3,7 +3,6 @@ // 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" @@ -33,9 +32,5 @@ 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; } diff --git a/shell/platform/android/vsync_waiter_android.cc b/shell/platform/android/vsync_waiter_android.cc index fa3630e08e168..1a69705f634d4 100644 --- a/shell/platform/android/vsync_waiter_android.cc +++ b/shell/platform/android/vsync_waiter_android.cc @@ -29,11 +29,13 @@ void VsyncWaiterAndroid::AwaitVSync() { auto* weak_this = new std::weak_ptr(shared_from_this()); jlong java_baton = reinterpret_cast(weak_this); - JNIEnv* env = fml::jni::AttachCurrentThread(); - env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), // - g_async_wait_for_vsync_method_, // - java_baton // - ); + 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 // + ); + }); } // static