Refactor NDK helpers some more, add methods for SurfaceControl/Transaction, tests (flutter/engine#50540)

Adds more dynamic method lookups in service of https://github.com/flutter/flutter/issues/143105

Moves the TU out to FML so that Impeller can more easily use it.

Adds checking on `AHardwareBuffer_getId` so that it checks the return value before returning what is potentially garbage.

Adds some smoke tests to make sure these things actually work/look up meaningful symbols. Test is in the shell because we have testing infra for this kind of thing there.
This commit is contained in:
Dan Field 2024-02-12 09:12:06 -08:00 committed by GitHub
parent daaedbbe2b
commit 2f964dfe37
18 changed files with 498 additions and 310 deletions

View File

@ -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

View File

@ -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
@ -6474,8 +6476,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
@ -7663,6 +7663,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
@ -9324,8 +9326,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

View File

@ -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",

View File

@ -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 <android/hardware_buffer.h>
#include <dlfcn.h>
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<fml::NativeLibrary> android =
fml::NativeLibrary::Create("libandroid.so");
FML_CHECK(android.get() != nullptr);
static fml::RefPtr<fml::NativeLibrary> egl =
fml::NativeLibrary::Create("libEGL.so");
FML_CHECK(egl.get() != nullptr);
#define LOOKUP(lib, func) \
_##func = lib->ResolveFunction<fp_##func>(#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<HardwareBufferKey> 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

View File

@ -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 <EGL/egl.h>
#include <android/choreographer.h>
#include <android/hardware_buffer.h>
#include <android/surface_control.h>
#include <android/trace.h>
#include <jni.h>
#include <optional>
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<HardwareBufferKey> AHardwareBuffer_getId(
AHardwareBuffer* _Nonnull buffer);
};
} // namespace flutter
#endif // FLUTTER_FML_PLATFORM_ANDROID_NDK_HELPERS_H_

View File

@ -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

View File

@ -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",

View File

@ -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"

View File

@ -4,8 +4,9 @@
#include <android/hardware_buffer_jni.h>
#include <android/sensor.h>
#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 {

View File

@ -8,11 +8,11 @@
#include <android/sensor.h>
#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"

View File

@ -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 {

View File

@ -2,6 +2,7 @@
#include "flutter/shell/platform/android/image_external_texture_vk.h"
#include <cstdint>
#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 {

View File

@ -9,7 +9,7 @@
#include <cstddef>
#include "display_list/image/dl_image.h"
#include "shell/platform/android/ndk_helpers.h"
#include "fml/platform/android/ndk_helpers.h"
namespace flutter {

View File

@ -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"

View File

@ -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 <android/hardware_buffer.h>
#include <dlfcn.h>
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<fml::NativeLibrary> android =
fml::NativeLibrary::Create("libandroid.so");
FML_CHECK(android.get() != nullptr);
static fml::RefPtr<fml::NativeLibrary> egl =
fml::NativeLibrary::Create("libEGL.so");
FML_CHECK(egl.get() != nullptr);
_eglGetNativeClientBufferANDROID =
egl->ResolveFunction<fp_eglGetNativeClientBufferANDROID>(
"eglGetNativeClientBufferANDROID")
.value_or(nullptr);
_AHardwareBuffer_fromHardwareBuffer =
android
->ResolveFunction<fp_AHardwareBuffer_fromHardwareBuffer>(
"AHardwareBuffer_fromHardwareBuffer")
.value_or(nullptr);
_AHardwareBuffer_acquire = android
->ResolveFunction<fp_AHardwareBuffer_acquire>(
"AHardwareBuffer_acquire")
.value_or(nullptr);
_AHardwareBuffer_release = android
->ResolveFunction<fp_AHardwareBuffer_release>(
"AHardwareBuffer_release")
.value_or(nullptr);
_AHardwareBuffer_getId =
android
->ResolveFunction<fp_AHardwareBuffer_getId>("AHardwareBuffer_getId")
.value_or(nullptr);
_AHardwareBuffer_describe =
android
->ResolveFunction<fp_AHardwareBuffer_describe>(
"AHardwareBuffer_describe")
.value_or(nullptr);
_ATrace_isEnabled =
android->ResolveFunction<fp_ATrace_isEnabled>("ATrace_isEnabled")
.value_or(nullptr);
_AChoreographer_getInstance =
android
->ResolveFunction<fp_AChoreographer_getInstance>(
"AChoreographer_getInstance")
.value_or(nullptr);
if (_AChoreographer_getInstance) {
_AChoreographer_postFrameCallback64 =
android
->ResolveFunction<fp_AChoreographer_postFrameCallback64>(
"AChoreographer_postFrameCallback64")
.value_or(nullptr);
#if FML_ARCH_CPU_64_BITS
if (!_AChoreographer_postFrameCallback64) {
_AChoreographer_postFrameCallback =
android
->ResolveFunction<fp_AChoreographer_postFrameCallback>(
"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<HardwareBufferKey> 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

View File

@ -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 <android/choreographer.h>
#include <android/hardware_buffer.h>
#include <android/surface_control.h>
#include <android/trace.h>
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<HardwareBufferKey> AHardwareBuffer_getId(
AHardwareBuffer* buffer);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_NDK_HELPERS_H_

View File

@ -12,7 +12,7 @@
#include <sstream>
#include <utility>
#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"

View File

@ -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 {