diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index 03144b461e073..e06c8ec8c27fa 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -100,6 +100,7 @@ ../../../flutter/fml/message_loop_task_queues_unittests.cc ../../../flutter/fml/message_loop_unittests.cc ../../../flutter/fml/paths_unittests.cc +../../../flutter/fml/platform/android/ndk_helpers_unittests.cc ../../../flutter/fml/platform/darwin/cf_utils_unittests.mm ../../../flutter/fml/platform/darwin/scoped_nsobject_arc_unittests.mm ../../../flutter/fml/platform/darwin/scoped_nsobject_unittests.mm diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 926171dd999c8..528857ff2038d 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -4832,6 +4832,8 @@ ORIGIN: ../../../flutter/fml/platform/android/jni_weak_ref.cc + ../../../flutter ORIGIN: ../../../flutter/fml/platform/android/jni_weak_ref.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/fml/platform/android/message_loop_android.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/fml/platform/android/message_loop_android.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/fml/platform/android/ndk_helpers.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/fml/platform/android/ndk_helpers.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/fml/platform/android/paths_android.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/fml/platform/android/paths_android.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/fml/platform/android/scoped_java_ref.cc + ../../../flutter/LICENSE @@ -6476,8 +6478,6 @@ ORIGIN: ../../../flutter/shell/platform/android/jni/jni_mock.h + ../../../flutte ORIGIN: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/library_loader.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/ndk_helpers.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/ndk_helpers.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/platform_message_handler_android.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/platform_message_response_android.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/platform_message_response_android.h + ../../../flutter/LICENSE @@ -7665,6 +7665,8 @@ FILE: ../../../flutter/fml/platform/android/jni_weak_ref.cc FILE: ../../../flutter/fml/platform/android/jni_weak_ref.h FILE: ../../../flutter/fml/platform/android/message_loop_android.cc FILE: ../../../flutter/fml/platform/android/message_loop_android.h +FILE: ../../../flutter/fml/platform/android/ndk_helpers.cc +FILE: ../../../flutter/fml/platform/android/ndk_helpers.h FILE: ../../../flutter/fml/platform/android/paths_android.cc FILE: ../../../flutter/fml/platform/android/paths_android.h FILE: ../../../flutter/fml/platform/android/scoped_java_ref.cc @@ -9328,8 +9330,6 @@ FILE: ../../../flutter/shell/platform/android/jni/jni_mock.h FILE: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.cc FILE: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.h FILE: ../../../flutter/shell/platform/android/library_loader.cc -FILE: ../../../flutter/shell/platform/android/ndk_helpers.cc -FILE: ../../../flutter/shell/platform/android/ndk_helpers.h FILE: ../../../flutter/shell/platform/android/platform_message_handler_android.cc FILE: ../../../flutter/shell/platform/android/platform_message_handler_android.h FILE: ../../../flutter/shell/platform/android/platform_message_response_android.cc diff --git a/fml/BUILD.gn b/fml/BUILD.gn index 3267884785744..088c391bdfdbc 100644 --- a/fml/BUILD.gn +++ b/fml/BUILD.gn @@ -184,6 +184,8 @@ source_set("fml") { "platform/android/jni_weak_ref.h", "platform/android/message_loop_android.cc", "platform/android/message_loop_android.h", + "platform/android/ndk_helpers.cc", + "platform/android/ndk_helpers.h", "platform/android/paths_android.cc", "platform/android/paths_android.h", "platform/android/scoped_java_ref.cc", diff --git a/fml/platform/android/ndk_helpers.cc b/fml/platform/android/ndk_helpers.cc new file mode 100644 index 0000000000000..67267435a82c4 --- /dev/null +++ b/fml/platform/android/ndk_helpers.cc @@ -0,0 +1,258 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fml/platform/android/ndk_helpers.h" + +#include "fml/logging.h" +#include "fml/native_library.h" + +#include +#include + +namespace flutter { + +namespace { + +#define DECLARE_TYPES(ret, name, args) \ + typedef ret(*fp_##name) args; \ + ret(*_##name) args = nullptr + +DECLARE_TYPES(int, + AHardwareBuffer_allocate, + (const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer)); +DECLARE_TYPES(int, + AHardwareBuffer_isSupported, + (const AHardwareBuffer_Desc* desc)); +DECLARE_TYPES(AHardwareBuffer*, + AHardwareBuffer_fromHardwareBuffer, + (JNIEnv * env, jobject hardwareBufferObj)); +DECLARE_TYPES(void, AHardwareBuffer_release, (AHardwareBuffer * buffer)); +DECLARE_TYPES(void, + AHardwareBuffer_describe, + (AHardwareBuffer * buffer, AHardwareBuffer_Desc* desc)); +DECLARE_TYPES(int, + AHardwareBuffer_getId, + (AHardwareBuffer * buffer, uint64_t* outId)); + +DECLARE_TYPES(bool, ATrace_isEnabled, (void)); + +DECLARE_TYPES(ASurfaceControl*, + ASurfaceControl_createFromWindow, + (ANativeWindow * parent, const char* debug_name)); +DECLARE_TYPES(void, + ASurfaceControl_release, + (ASurfaceControl * surface_control)); +DECLARE_TYPES(ASurfaceTransaction*, ASurfaceTransaction_create, (void)); +DECLARE_TYPES(void, + ASurfaceTransaction_delete, + (ASurfaceTransaction * surface_transaction)); +DECLARE_TYPES(void, + ASurfaceTransaction_apply, + (ASurfaceTransaction * surface_transaction)); +DECLARE_TYPES(void, + ASurfaceTransaction_setBuffer, + (ASurfaceTransaction * transaction, + ASurfaceControl* surface_control, + AHardwareBuffer* buffer, + int acquire_fence_fd)); + +DECLARE_TYPES(AChoreographer*, AChoreographer_getInstance, (void)); +DECLARE_TYPES(void, + AChoreographer_postFrameCallback, + (AChoreographer * choreographer, + AChoreographer_frameCallback callbackk, + void* data)); +DECLARE_TYPES(void, + AChoreographer_postFrameCallback64, + (AChoreographer * choreographer, + AChoreographer_frameCallback64 callbackk, + void* data)); + +DECLARE_TYPES(EGLClientBuffer, + eglGetNativeClientBufferANDROID, + (AHardwareBuffer * buffer)); + +#undef DECLARE_TYPES + +std::once_flag init_once; + +void InitOnceCallback() { + static fml::RefPtr android = + fml::NativeLibrary::Create("libandroid.so"); + FML_CHECK(android.get() != nullptr); + static fml::RefPtr egl = + fml::NativeLibrary::Create("libEGL.so"); + FML_CHECK(egl.get() != nullptr); + +#define LOOKUP(lib, func) \ + _##func = lib->ResolveFunction(#func).value_or(nullptr) + + LOOKUP(egl, eglGetNativeClientBufferANDROID); + + LOOKUP(android, AHardwareBuffer_fromHardwareBuffer); + LOOKUP(android, AHardwareBuffer_release); + LOOKUP(android, AHardwareBuffer_getId); + LOOKUP(android, AHardwareBuffer_describe); + LOOKUP(android, AHardwareBuffer_allocate); + LOOKUP(android, AHardwareBuffer_isSupported); + LOOKUP(android, ATrace_isEnabled); + LOOKUP(android, AChoreographer_getInstance); + if (_AChoreographer_getInstance) { + LOOKUP(android, AChoreographer_postFrameCallback64); + if (!_AChoreographer_postFrameCallback64) { + LOOKUP(android, AChoreographer_postFrameCallback); + } + } + + LOOKUP(android, ASurfaceControl_createFromWindow); + LOOKUP(android, ASurfaceControl_release); + LOOKUP(android, ASurfaceTransaction_apply); + LOOKUP(android, ASurfaceTransaction_create); + LOOKUP(android, ASurfaceTransaction_delete); + LOOKUP(android, ASurfaceTransaction_setBuffer); +#undef LOOKUP +} + +} // namespace + +void NDKHelpers::Init() { + std::call_once(init_once, InitOnceCallback); +} + +bool NDKHelpers::ATrace_isEnabled() { + if (_ATrace_isEnabled) { + return _ATrace_isEnabled(); + } + return false; +} + +ChoreographerSupportStatus NDKHelpers::ChoreographerSupported() { + if (_AChoreographer_postFrameCallback64) { + return ChoreographerSupportStatus::kSupported64; + } + if (_AChoreographer_postFrameCallback) { + return ChoreographerSupportStatus::kSupported32; + } + return ChoreographerSupportStatus::kUnsupported; +} + +AChoreographer* NDKHelpers::AChoreographer_getInstance() { + FML_CHECK(_AChoreographer_getInstance); + return _AChoreographer_getInstance(); +} + +void NDKHelpers::AChoreographer_postFrameCallback( + AChoreographer* choreographer, + AChoreographer_frameCallback callback, + void* data) { + FML_CHECK(_AChoreographer_postFrameCallback); + return _AChoreographer_postFrameCallback(choreographer, callback, data); +} + +void NDKHelpers::AChoreographer_postFrameCallback64( + AChoreographer* choreographer, + AChoreographer_frameCallback64 callback, + void* data) { + FML_CHECK(_AChoreographer_postFrameCallback64); + return _AChoreographer_postFrameCallback64(choreographer, callback, data); +} + +bool NDKHelpers::HardwareBufferSupported() { + const bool r = _AHardwareBuffer_fromHardwareBuffer != nullptr; + return r; +} + +AHardwareBuffer* NDKHelpers::AHardwareBuffer_fromHardwareBuffer( + JNIEnv* env, + jobject hardwareBufferObj) { + FML_CHECK(_AHardwareBuffer_fromHardwareBuffer != nullptr); + return _AHardwareBuffer_fromHardwareBuffer(env, hardwareBufferObj); +} + +void NDKHelpers::AHardwareBuffer_release(AHardwareBuffer* buffer) { + FML_CHECK(_AHardwareBuffer_release != nullptr); + _AHardwareBuffer_release(buffer); +} + +void NDKHelpers::AHardwareBuffer_describe(AHardwareBuffer* buffer, + AHardwareBuffer_Desc* desc) { + FML_CHECK(_AHardwareBuffer_describe != nullptr); + _AHardwareBuffer_describe(buffer, desc); +} + +std::optional NDKHelpers::AHardwareBuffer_getId( + AHardwareBuffer* buffer) { + if (_AHardwareBuffer_getId == nullptr) { + return std::nullopt; + } + HardwareBufferKey outId; + int result = _AHardwareBuffer_getId(buffer, &outId); + if (result == 0) { + return outId; + } + return std::nullopt; +} + +EGLClientBuffer NDKHelpers::eglGetNativeClientBufferANDROID( + AHardwareBuffer* buffer) { + FML_CHECK(_eglGetNativeClientBufferANDROID != nullptr); + return _eglGetNativeClientBufferANDROID(buffer); +} + +bool NDKHelpers::SurfaceControlAndTransactionSupported() { + return _ASurfaceControl_createFromWindow && _ASurfaceControl_release && + _ASurfaceTransaction_create && _ASurfaceTransaction_apply && + _ASurfaceTransaction_delete && _ASurfaceTransaction_setBuffer; +} + +ASurfaceControl* NDKHelpers::ASurfaceControl_createFromWindow( + ANativeWindow* parent, + const char* debug_name) { + FML_CHECK(_ASurfaceControl_createFromWindow); + return _ASurfaceControl_createFromWindow(parent, debug_name); +} + +void NDKHelpers::ASurfaceControl_release(ASurfaceControl* surface_control) { + FML_CHECK(_ASurfaceControl_release); + return _ASurfaceControl_release(surface_control); +} + +ASurfaceTransaction* NDKHelpers::ASurfaceTransaction_create() { + FML_CHECK(_ASurfaceTransaction_create); + return _ASurfaceTransaction_create(); +} + +void NDKHelpers::ASurfaceTransaction_delete( + ASurfaceTransaction* surface_transaction) { + FML_CHECK(_ASurfaceTransaction_delete); + _ASurfaceTransaction_delete(surface_transaction); +} + +void NDKHelpers::ASurfaceTransaction_apply( + ASurfaceTransaction* surface_transaction) { + FML_CHECK(_ASurfaceTransaction_apply); + _ASurfaceTransaction_apply(surface_transaction); +} + +void NDKHelpers::ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, + AHardwareBuffer* buffer, + int acquire_fence_fd) { + FML_CHECK(_ASurfaceTransaction_setBuffer); + _ASurfaceTransaction_setBuffer(transaction, surface_control, buffer, + acquire_fence_fd); +} + +int NDKHelpers::AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) { + FML_CHECK(_AHardwareBuffer_isSupported); + return _AHardwareBuffer_isSupported(desc); +} + +int NDKHelpers::AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, + AHardwareBuffer** outBuffer) { + FML_CHECK(_AHardwareBuffer_allocate); + return _AHardwareBuffer_allocate(desc, outBuffer); +} + +} // namespace flutter diff --git a/fml/platform/android/ndk_helpers.h b/fml/platform/android/ndk_helpers.h new file mode 100644 index 0000000000000..9299776e3e691 --- /dev/null +++ b/fml/platform/android/ndk_helpers.h @@ -0,0 +1,100 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_FML_PLATFORM_ANDROID_NDK_HELPERS_H_ +#define FLUTTER_FML_PLATFORM_ANDROID_NDK_HELPERS_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace flutter { + +using HardwareBufferKey = uint64_t; + +enum class ChoreographerSupportStatus { + // Unavailable, API level < 24. + kUnsupported, + // Available, but only with postFrameCallback. + kSupported32, + // Available, but only with postFrameCallback64. + kSupported64, +}; + +// A collection of NDK functions that are available depending on the version of +// the Android SDK we are linked with at runtime. +class NDKHelpers { + public: + // Safe to call multiple times. + // Normally called from JNI_OnLoad. + static void Init(); + + // API Version 23 + static bool ATrace_isEnabled(); + + // API Version 24 + static ChoreographerSupportStatus ChoreographerSupported(); + static AChoreographer* _Nullable AChoreographer_getInstance(); + // Deprecated in 29, available since 24. + static void AChoreographer_postFrameCallback( + AChoreographer* _Nonnull choreographer, + AChoreographer_frameCallback _Nonnull callback, + void* _Nullable data); + + // API Version 26 + static bool HardwareBufferSupported(); + static AHardwareBuffer* _Nonnull AHardwareBuffer_fromHardwareBuffer( + JNIEnv* _Nonnull env, + jobject _Nonnull hardwareBufferObj); + static void AHardwareBuffer_release(AHardwareBuffer* _Nonnull buffer); + static void AHardwareBuffer_describe(AHardwareBuffer* _Nonnull buffer, + AHardwareBuffer_Desc* _Nullable desc); + static int AHardwareBuffer_allocate( + const AHardwareBuffer_Desc* _Nonnull desc, + AHardwareBuffer* _Nullable* _Nullable outBuffer); + static EGLClientBuffer _Nonnull eglGetNativeClientBufferANDROID( + AHardwareBuffer* _Nonnull buffer); + + // API Version 29 + static int AHardwareBuffer_isSupported( + const AHardwareBuffer_Desc* _Nonnull desc); + + static void AChoreographer_postFrameCallback64( + AChoreographer* _Nonnull choreographer, + AChoreographer_frameCallback64 _Nonnull callback, + void* _Nullable data); + + static bool SurfaceControlAndTransactionSupported(); + + static ASurfaceControl* _Nonnull ASurfaceControl_createFromWindow( + ANativeWindow* _Nonnull parent, + const char* _Nullable debug_name); + static void ASurfaceControl_release( + ASurfaceControl* _Nonnull surface_control); + + static ASurfaceTransaction* _Nonnull ASurfaceTransaction_create(); + static void ASurfaceTransaction_delete( + ASurfaceTransaction* _Nonnull surface_transaction); + static void ASurfaceTransaction_apply( + ASurfaceTransaction* _Nonnull surface_transaction); + static void ASurfaceTransaction_setBuffer( + ASurfaceTransaction* _Nonnull transaction, + ASurfaceControl* _Nonnull surface_control, + AHardwareBuffer* _Nonnull buffer, + int acquire_fence_fd); + + // API Version 31 + + // Returns std::nullopt on API version 26 - 30. + static std::optional AHardwareBuffer_getId( + AHardwareBuffer* _Nonnull buffer); +}; + +} // namespace flutter + +#endif // FLUTTER_FML_PLATFORM_ANDROID_NDK_HELPERS_H_ diff --git a/fml/platform/android/ndk_helpers_unittests.cc b/fml/platform/android/ndk_helpers_unittests.cc new file mode 100644 index 0000000000000..e6cab428cdbc8 --- /dev/null +++ b/fml/platform/android/ndk_helpers_unittests.cc @@ -0,0 +1,121 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fml/message_loop.h" +#include "fml/platform/android/ndk_helpers.h" + +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +namespace android { + +class NdkHelpersTest : public ::testing::Test { + public: + void SetUp() override { NDKHelpers::Init(); } + + static void OnVsync(int64_t frame_nanos, void* data) {} + static void OnVsync32( + long frame_nanos, // NOLINT - compat for deprecated call + void* data) {} +}; + +TEST_F(NdkHelpersTest, ATrace) { + ASSERT_GT(android_get_device_api_level(), 22); + EXPECT_FALSE(NDKHelpers::ATrace_isEnabled()); +} + +TEST_F(NdkHelpersTest, AChoreographer32) { + if (android_get_device_api_level() >= 29) { + GTEST_SKIP() << "This test is for less than API 29."; + } + + EXPECT_EQ(NDKHelpers::ChoreographerSupported(), + ChoreographerSupportStatus::kSupported32); + + EXPECT_FALSE(NDKHelpers::AChoreographer_getInstance()); + + fml::MessageLoop::EnsureInitializedForCurrentThread(); + + EXPECT_TRUE(NDKHelpers::AChoreographer_getInstance()); + + NDKHelpers::AChoreographer_postFrameCallback( + NDKHelpers::AChoreographer_getInstance(), &OnVsync32, nullptr); +} + +TEST_F(NdkHelpersTest, AChoreographer64) { + if (android_get_device_api_level() < 29) { + GTEST_SKIP() << "This test is for API 29 and above."; + } + + EXPECT_EQ(NDKHelpers::ChoreographerSupported(), + ChoreographerSupportStatus::kSupported64); + + EXPECT_FALSE(NDKHelpers::AChoreographer_getInstance()); + + fml::MessageLoop::EnsureInitializedForCurrentThread(); + + EXPECT_TRUE(NDKHelpers::AChoreographer_getInstance()); + + NDKHelpers::AChoreographer_postFrameCallback64( + NDKHelpers::AChoreographer_getInstance(), &OnVsync, nullptr); +} + +TEST_F(NdkHelpersTest, HardwareBuffer) { + if (android_get_device_api_level() < 26) { + GTEST_SKIP() << "Test requires at least API 26."; + } + + ASSERT_TRUE(NDKHelpers::HardwareBufferSupported()); + + AHardwareBuffer_Desc desc{ + .width = 4, + .height = 4, + .layers = 1, + .format = AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + }; + if (android_get_device_api_level() >= 29) { + EXPECT_TRUE(NDKHelpers::AHardwareBuffer_isSupported(&desc)); + } + + AHardwareBuffer* buffer = nullptr; + // AHardwareBuffer_allocate returns 0 on success. + EXPECT_EQ(NDKHelpers::AHardwareBuffer_allocate(&desc, &buffer), 0); + EXPECT_TRUE(buffer); + + AHardwareBuffer_Desc out_desc = {}; + NDKHelpers::AHardwareBuffer_describe(buffer, &out_desc); + EXPECT_EQ(desc.width, out_desc.width); + EXPECT_EQ(desc.height, out_desc.height); + EXPECT_EQ(desc.layers, out_desc.layers); + EXPECT_EQ(desc.format, out_desc.format); + + auto id = NDKHelpers::AHardwareBuffer_getId(buffer); + if (android_get_device_api_level() >= 31) { + EXPECT_TRUE(id.has_value()); + } else { + EXPECT_FALSE(id.has_value()); + } + + NDKHelpers::AHardwareBuffer_release(buffer); +} + +TEST_F(NdkHelpersTest, SurfaceTransaction) { + if (android_get_device_api_level() < 29) { + GTEST_SKIP() << "Test requires at least API 29."; + } + EXPECT_TRUE(NDKHelpers::SurfaceControlAndTransactionSupported()); + + // Need ANativeWindow to create ASurfaceControl and set a buffer to the + // transaction. Just create/apply/delete as a smoke test. + + ASurfaceTransaction* transaction = NDKHelpers::ASurfaceTransaction_create(); + EXPECT_TRUE(transaction); + NDKHelpers::ASurfaceTransaction_apply(transaction); + NDKHelpers::ASurfaceTransaction_delete(transaction); +} + +} // namespace android +} // namespace testing +} // namespace flutter diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 21429607f2435..a6c4cb6078bc0 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -42,6 +42,7 @@ executable("flutter_shell_native_unittests") { visibility = [ "*" ] testonly = true sources = [ + "//flutter/fml/platform/android/ndk_helpers_unittests.cc", "android_context_gl_impeller_unittests.cc", "android_context_gl_unittests.cc", "android_shell_holder_unittests.cc", @@ -53,6 +54,7 @@ executable("flutter_shell_native_unittests") { public_configs = [ "//flutter:config" ] deps = [ ":flutter_shell_native_src", + "//flutter/fml", "//flutter/shell/platform/android/jni:jni_mock", "//third_party/googletest:gmock", "//third_party/googletest:gtest", @@ -113,8 +115,6 @@ source_set("flutter_shell_native_src") { "image_lru.cc", "image_lru.h", "library_loader.cc", - "ndk_helpers.cc", - "ndk_helpers.h", "platform_message_handler_android.cc", "platform_message_handler_android.h", "platform_message_response_android.cc", diff --git a/shell/platform/android/flutter_main.cc b/shell/platform/android/flutter_main.cc index 8a2e9eaca5e66..6ad57a7ca04cc 100644 --- a/shell/platform/android/flutter_main.cc +++ b/shell/platform/android/flutter_main.cc @@ -18,13 +18,13 @@ #include "flutter/fml/native_library.h" #include "flutter/fml/paths.h" #include "flutter/fml/platform/android/jni_util.h" +#include "flutter/fml/platform/android/ndk_helpers.h" #include "flutter/fml/platform/android/paths_android.h" #include "flutter/fml/size.h" #include "flutter/lib/ui/plugins/callback_cache.h" #include "flutter/runtime/dart_vm.h" #include "flutter/shell/common/shell.h" #include "flutter/shell/common/switches.h" -#include "flutter/shell/platform/android/ndk_helpers.h" #include "third_party/dart/runtime/include/dart_tools_api.h" #include "txt/platform.h" diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index da6f55832672e..855b56d2b77d8 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -4,8 +4,9 @@ #include #include +#include "flutter/fml/platform/android/jni_util.h" +#include "flutter/fml/platform/android/ndk_helpers.h" #include "flutter/shell/platform/android/jni/platform_view_android_jni.h" -#include "flutter/shell/platform/android/ndk_helpers.h" namespace flutter { diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index 1dea2df1eed7e..6a676e90cbf22 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -8,11 +8,11 @@ #include #include "flutter/common/graphics/texture.h" +#include "flutter/fml/platform/android/ndk_helpers.h" #include "flutter/impeller/core/formats.h" #include "flutter/impeller/display_list/dl_image_impeller.h" #include "flutter/impeller/toolkit/egl/image.h" #include "flutter/impeller/toolkit/gles/texture.h" -#include "flutter/shell/platform/android/ndk_helpers.h" #include "third_party/skia/include/core/SkAlphaType.h" #include "third_party/skia/include/core/SkColorType.h" #include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index e3040d5e58489..8aeec744ab0cd 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -17,8 +17,8 @@ #include "flutter/impeller/toolkit/egl/image.h" #include "flutter/impeller/toolkit/gles/texture.h" +#include "flutter/fml/platform/android/ndk_helpers.h" #include "flutter/shell/platform/android/android_context_gl_skia.h" -#include "flutter/shell/platform/android/ndk_helpers.h" namespace flutter { diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index 5eaf47083e6cb..9af0683340b1f 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -2,6 +2,7 @@ #include "flutter/shell/platform/android/image_external_texture_vk.h" #include +#include "flutter/fml/platform/android/ndk_helpers.h" #include "flutter/impeller/core/formats.h" #include "flutter/impeller/core/texture_descriptor.h" #include "flutter/impeller/display_list/dl_image_impeller.h" @@ -9,7 +10,6 @@ #include "flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h" #include "flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h" #include "flutter/impeller/renderer/backend/vulkan/texture_vk.h" -#include "flutter/shell/platform/android/ndk_helpers.h" namespace flutter { diff --git a/shell/platform/android/image_lru.h b/shell/platform/android/image_lru.h index 34fa97c37cce4..28a31cd2bf842 100644 --- a/shell/platform/android/image_lru.h +++ b/shell/platform/android/image_lru.h @@ -9,7 +9,7 @@ #include #include "display_list/image/dl_image.h" -#include "shell/platform/android/ndk_helpers.h" +#include "fml/platform/android/ndk_helpers.h" namespace flutter { diff --git a/shell/platform/android/library_loader.cc b/shell/platform/android/library_loader.cc index 103a3aeb2a111..9f3691d818512 100644 --- a/shell/platform/android/library_loader.cc +++ b/shell/platform/android/library_loader.cc @@ -3,9 +3,9 @@ // found in the LICENSE file. #include "flutter/fml/platform/android/jni_util.h" +#include "flutter/fml/platform/android/ndk_helpers.h" #include "flutter/shell/platform/android/android_image_generator.h" #include "flutter/shell/platform/android/flutter_main.h" -#include "flutter/shell/platform/android/ndk_helpers.h" #include "flutter/shell/platform/android/platform_view_android.h" #include "flutter/shell/platform/android/vsync_waiter_android.h" diff --git a/shell/platform/android/ndk_helpers.cc b/shell/platform/android/ndk_helpers.cc deleted file mode 100644 index 65fc9368c8ad3..0000000000000 --- a/shell/platform/android/ndk_helpers.cc +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/shell/platform/android/ndk_helpers.h" - -#include "fml/native_library.h" - -#include "flutter/fml/logging.h" - -#include -#include - -namespace flutter { - -namespace { - -typedef AHardwareBuffer* (*fp_AHardwareBuffer_fromHardwareBuffer)( - JNIEnv* env, - jobject hardwareBufferObj); -typedef void (*fp_AHardwareBuffer_acquire)(AHardwareBuffer* buffer); -typedef void (*fp_AHardwareBuffer_release)(AHardwareBuffer* buffer); -typedef void (*fp_AHardwareBuffer_describe)(AHardwareBuffer* buffer, - AHardwareBuffer_Desc* desc); -typedef void (*fp_AHardwareBuffer_getId)(AHardwareBuffer* buffer, - uint64_t* outId); - -typedef bool (*fp_ATrace_isEnabled)(void); - -typedef AChoreographer* (*fp_AChoreographer_getInstance)(void); -typedef void (*fp_AChoreographer_postFrameCallback)( - AChoreographer* choreographer, - AChoreographer_frameCallback callbackk, - void* data); -typedef void (*fp_AChoreographer_postFrameCallback64)( - AChoreographer* choreographer, - AChoreographer_frameCallback64 callbackk, - void* data); - -typedef EGLClientBuffer (*fp_eglGetNativeClientBufferANDROID)( - AHardwareBuffer* buffer); - -AHardwareBuffer* (*_AHardwareBuffer_fromHardwareBuffer)( - JNIEnv* env, - jobject hardwareBufferObj) = nullptr; -void (*_AHardwareBuffer_acquire)(AHardwareBuffer* buffer) = nullptr; -void (*_AHardwareBuffer_release)(AHardwareBuffer* buffer) = nullptr; -void (*_AHardwareBuffer_describe)(AHardwareBuffer* buffer, - AHardwareBuffer_Desc* desc) = nullptr; -void (*_AHardwareBuffer_getId)(AHardwareBuffer* buffer, - uint64_t* outId) = nullptr; -bool (*_ATrace_isEnabled)() = nullptr; -AChoreographer* (*_AChoreographer_getInstance)() = nullptr; -void (*_AChoreographer_postFrameCallback)( - AChoreographer* choreographer, - AChoreographer_frameCallback callbackk, - void* data) = nullptr; -void (*_AChoreographer_postFrameCallback64)( - AChoreographer* choreographer, - AChoreographer_frameCallback64 callbackk, - void* data) = nullptr; - -EGLClientBuffer (*_eglGetNativeClientBufferANDROID)(AHardwareBuffer* buffer) = - nullptr; - -std::once_flag init_once; - -void InitOnceCallback() { - static fml::RefPtr android = - fml::NativeLibrary::Create("libandroid.so"); - FML_CHECK(android.get() != nullptr); - static fml::RefPtr egl = - fml::NativeLibrary::Create("libEGL.so"); - FML_CHECK(egl.get() != nullptr); - _eglGetNativeClientBufferANDROID = - egl->ResolveFunction( - "eglGetNativeClientBufferANDROID") - .value_or(nullptr); - _AHardwareBuffer_fromHardwareBuffer = - android - ->ResolveFunction( - "AHardwareBuffer_fromHardwareBuffer") - .value_or(nullptr); - _AHardwareBuffer_acquire = android - ->ResolveFunction( - "AHardwareBuffer_acquire") - .value_or(nullptr); - _AHardwareBuffer_release = android - ->ResolveFunction( - "AHardwareBuffer_release") - .value_or(nullptr); - _AHardwareBuffer_getId = - android - ->ResolveFunction("AHardwareBuffer_getId") - .value_or(nullptr); - _AHardwareBuffer_describe = - android - ->ResolveFunction( - "AHardwareBuffer_describe") - .value_or(nullptr); - - _ATrace_isEnabled = - android->ResolveFunction("ATrace_isEnabled") - .value_or(nullptr); - - _AChoreographer_getInstance = - android - ->ResolveFunction( - "AChoreographer_getInstance") - .value_or(nullptr); - if (_AChoreographer_getInstance) { - _AChoreographer_postFrameCallback64 = - android - ->ResolveFunction( - "AChoreographer_postFrameCallback64") - .value_or(nullptr); -#if FML_ARCH_CPU_64_BITS - if (!_AChoreographer_postFrameCallback64) { - _AChoreographer_postFrameCallback = - android - ->ResolveFunction( - "AChoreographer_postFrameCallback") - .value_or(nullptr); - } -#endif - } -} - -} // namespace - -void NDKHelpers::Init() { - std::call_once(init_once, InitOnceCallback); -} - -bool NDKHelpers::ATrace_isEnabled() { - if (_ATrace_isEnabled) { - return _ATrace_isEnabled(); - } - return false; -} - -ChoreographerSupportStatus NDKHelpers::ChoreographerSupported() { - if (_AChoreographer_postFrameCallback64) { - return ChoreographerSupportStatus::kSupported64; - } - if (_AChoreographer_postFrameCallback) { - return ChoreographerSupportStatus::kSupported32; - } - return ChoreographerSupportStatus::kUnsupported; -} - -AChoreographer* NDKHelpers::AChoreographer_getInstance() { - FML_CHECK(_AChoreographer_getInstance); - return _AChoreographer_getInstance(); -} - -void NDKHelpers::AChoreographer_postFrameCallback( - AChoreographer* choreographer, - AChoreographer_frameCallback callback, - void* data) { - FML_CHECK(_AChoreographer_postFrameCallback); - return _AChoreographer_postFrameCallback(choreographer, callback, data); -} - -void NDKHelpers::AChoreographer_postFrameCallback64( - AChoreographer* choreographer, - AChoreographer_frameCallback64 callback, - void* data) { - FML_CHECK(_AChoreographer_postFrameCallback64); - return _AChoreographer_postFrameCallback64(choreographer, callback, data); -} - -bool NDKHelpers::HardwareBufferSupported() { - const bool r = _AHardwareBuffer_fromHardwareBuffer != nullptr; - return r; -} - -AHardwareBuffer* NDKHelpers::AHardwareBuffer_fromHardwareBuffer( - JNIEnv* env, - jobject hardwareBufferObj) { - FML_CHECK(_AHardwareBuffer_fromHardwareBuffer != nullptr); - return _AHardwareBuffer_fromHardwareBuffer(env, hardwareBufferObj); -} - -void NDKHelpers::AHardwareBuffer_acquire(AHardwareBuffer* buffer) { - FML_CHECK(_AHardwareBuffer_acquire != nullptr); - _AHardwareBuffer_acquire(buffer); -} - -void NDKHelpers::AHardwareBuffer_release(AHardwareBuffer* buffer) { - FML_CHECK(_AHardwareBuffer_release != nullptr); - _AHardwareBuffer_release(buffer); -} - -void NDKHelpers::AHardwareBuffer_describe(AHardwareBuffer* buffer, - AHardwareBuffer_Desc* desc) { - FML_CHECK(_AHardwareBuffer_describe != nullptr); - _AHardwareBuffer_describe(buffer, desc); -} - -std::optional NDKHelpers::AHardwareBuffer_getId( - AHardwareBuffer* buffer) { - if (_AHardwareBuffer_getId == nullptr) { - return std::nullopt; - } - HardwareBufferKey outId; - _AHardwareBuffer_getId(buffer, &outId); - return outId; -} - -EGLClientBuffer NDKHelpers::eglGetNativeClientBufferANDROID( - AHardwareBuffer* buffer) { - FML_CHECK(_eglGetNativeClientBufferANDROID != nullptr); - return _eglGetNativeClientBufferANDROID(buffer); -} - -} // namespace flutter diff --git a/shell/platform/android/ndk_helpers.h b/shell/platform/android/ndk_helpers.h deleted file mode 100644 index 5b7856aa6e241..0000000000000 --- a/shell/platform/android/ndk_helpers.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_NDK_HELPERS_H_ -#define FLUTTER_SHELL_PLATFORM_ANDROID_NDK_HELPERS_H_ - -#include "flutter/fml/native_library.h" -#include "flutter/fml/platform/android/jni_util.h" - -#include "flutter/impeller/toolkit/egl/egl.h" - -#include -#include -#include -#include - -namespace flutter { - -using HardwareBufferKey = uint64_t; - -enum class ChoreographerSupportStatus { - // Unavailable, API level < 24. - kUnsupported, - // Available, but only with postFrameCallback. - kSupported32, - // Available, but only with postFrameCallback64. - kSupported64, -}; - -// A collection of NDK functions that are available depending on the version of -// the Android SDK we are linked with at runtime. -class NDKHelpers { - public: - // Safe to call multiple times. - // Normally called from JNI_OnLoad. - static void Init(); - - // API Version 23 - static bool ATrace_isEnabled(); - - // API Version 24 - static ChoreographerSupportStatus ChoreographerSupported(); - static AChoreographer* AChoreographer_getInstance(); - // Deprecated in 29, available since 24. - static void AChoreographer_postFrameCallback( - AChoreographer* choreographer, - AChoreographer_frameCallback callback, - void* data); - - // API Version 26 - static bool HardwareBufferSupported(); - static AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer( - JNIEnv* env, - jobject hardwareBufferObj); - static void AHardwareBuffer_acquire(AHardwareBuffer* buffer); - static void AHardwareBuffer_release(AHardwareBuffer* buffer); - static void AHardwareBuffer_describe(AHardwareBuffer* buffer, - AHardwareBuffer_Desc* desc); - static EGLClientBuffer eglGetNativeClientBufferANDROID( - AHardwareBuffer* buffer); - - // API Version 29 - static void AChoreographer_postFrameCallback64( - AChoreographer* choreographer, - AChoreographer_frameCallback64 callback, - void* data); - - // API Version 31 - - // Returns std::nullopt on API version 26 - 30. - static std::optional AHardwareBuffer_getId( - AHardwareBuffer* buffer); -}; - -} // namespace flutter - -#endif // FLUTTER_SHELL_PLATFORM_ANDROID_NDK_HELPERS_H_ diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index 7d13c10949a68..b6d5dfc2f504f 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -12,7 +12,7 @@ #include #include -#include "flutter/shell/platform/android/ndk_helpers.h" +#include "flutter/fml/platform/android/ndk_helpers.h" #include "include/android/SkImageAndroid.h" #include "unicode/uchar.h" diff --git a/shell/platform/android/vsync_waiter_android.cc b/shell/platform/android/vsync_waiter_android.cc index 7b7f136257ce2..d0a8db383a0ce 100644 --- a/shell/platform/android/vsync_waiter_android.cc +++ b/shell/platform/android/vsync_waiter_android.cc @@ -10,10 +10,10 @@ #include "flutter/common/task_runners.h" #include "flutter/fml/logging.h" #include "flutter/fml/platform/android/jni_util.h" +#include "flutter/fml/platform/android/ndk_helpers.h" #include "flutter/fml/platform/android/scoped_java_ref.h" #include "flutter/fml/size.h" #include "flutter/fml/trace_event.h" -#include "flutter/shell/platform/android/ndk_helpers.h" namespace flutter {