Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor NDK helpers some more, add methods for SurfaceControl/Transaction, tests #50540

Merged
merged 6 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/excluded_files
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions fml/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
258 changes: 258 additions & 0 deletions fml/platform/android/ndk_helpers.cc
Original file line number Diff line number Diff line change
@@ -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
Loading