Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a119a0d

Browse files
authored
Refactor NDK helpers some more, add methods for SurfaceControl/Transaction, tests (#50540)
Adds more dynamic method lookups in service of flutter/flutter#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.
1 parent ccd90ff commit a119a0d

18 files changed

+498
-310
lines changed

ci/licenses_golden/excluded_files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
../../../flutter/fml/message_loop_task_queues_unittests.cc
101101
../../../flutter/fml/message_loop_unittests.cc
102102
../../../flutter/fml/paths_unittests.cc
103+
../../../flutter/fml/platform/android/ndk_helpers_unittests.cc
103104
../../../flutter/fml/platform/darwin/cf_utils_unittests.mm
104105
../../../flutter/fml/platform/darwin/scoped_nsobject_arc_unittests.mm
105106
../../../flutter/fml/platform/darwin/scoped_nsobject_unittests.mm

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4832,6 +4832,8 @@ ORIGIN: ../../../flutter/fml/platform/android/jni_weak_ref.cc + ../../../flutter
48324832
ORIGIN: ../../../flutter/fml/platform/android/jni_weak_ref.h + ../../../flutter/LICENSE
48334833
ORIGIN: ../../../flutter/fml/platform/android/message_loop_android.cc + ../../../flutter/LICENSE
48344834
ORIGIN: ../../../flutter/fml/platform/android/message_loop_android.h + ../../../flutter/LICENSE
4835+
ORIGIN: ../../../flutter/fml/platform/android/ndk_helpers.cc + ../../../flutter/LICENSE
4836+
ORIGIN: ../../../flutter/fml/platform/android/ndk_helpers.h + ../../../flutter/LICENSE
48354837
ORIGIN: ../../../flutter/fml/platform/android/paths_android.cc + ../../../flutter/LICENSE
48364838
ORIGIN: ../../../flutter/fml/platform/android/paths_android.h + ../../../flutter/LICENSE
48374839
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
64746476
ORIGIN: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.cc + ../../../flutter/LICENSE
64756477
ORIGIN: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.h + ../../../flutter/LICENSE
64766478
ORIGIN: ../../../flutter/shell/platform/android/library_loader.cc + ../../../flutter/LICENSE
6477-
ORIGIN: ../../../flutter/shell/platform/android/ndk_helpers.cc + ../../../flutter/LICENSE
6478-
ORIGIN: ../../../flutter/shell/platform/android/ndk_helpers.h + ../../../flutter/LICENSE
64796479
ORIGIN: ../../../flutter/shell/platform/android/platform_message_handler_android.h + ../../../flutter/LICENSE
64806480
ORIGIN: ../../../flutter/shell/platform/android/platform_message_response_android.cc + ../../../flutter/LICENSE
64816481
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
76637663
FILE: ../../../flutter/fml/platform/android/jni_weak_ref.h
76647664
FILE: ../../../flutter/fml/platform/android/message_loop_android.cc
76657665
FILE: ../../../flutter/fml/platform/android/message_loop_android.h
7666+
FILE: ../../../flutter/fml/platform/android/ndk_helpers.cc
7667+
FILE: ../../../flutter/fml/platform/android/ndk_helpers.h
76667668
FILE: ../../../flutter/fml/platform/android/paths_android.cc
76677669
FILE: ../../../flutter/fml/platform/android/paths_android.h
76687670
FILE: ../../../flutter/fml/platform/android/scoped_java_ref.cc
@@ -9324,8 +9326,6 @@ FILE: ../../../flutter/shell/platform/android/jni/jni_mock.h
93249326
FILE: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.cc
93259327
FILE: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.h
93269328
FILE: ../../../flutter/shell/platform/android/library_loader.cc
9327-
FILE: ../../../flutter/shell/platform/android/ndk_helpers.cc
9328-
FILE: ../../../flutter/shell/platform/android/ndk_helpers.h
93299329
FILE: ../../../flutter/shell/platform/android/platform_message_handler_android.cc
93309330
FILE: ../../../flutter/shell/platform/android/platform_message_handler_android.h
93319331
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.cc

fml/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ source_set("fml") {
184184
"platform/android/jni_weak_ref.h",
185185
"platform/android/message_loop_android.cc",
186186
"platform/android/message_loop_android.h",
187+
"platform/android/ndk_helpers.cc",
188+
"platform/android/ndk_helpers.h",
187189
"platform/android/paths_android.cc",
188190
"platform/android/paths_android.h",
189191
"platform/android/scoped_java_ref.cc",
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "fml/platform/android/ndk_helpers.h"
6+
7+
#include "fml/logging.h"
8+
#include "fml/native_library.h"
9+
10+
#include <android/hardware_buffer.h>
11+
#include <dlfcn.h>
12+
13+
namespace flutter {
14+
15+
namespace {
16+
17+
#define DECLARE_TYPES(ret, name, args) \
18+
typedef ret(*fp_##name) args; \
19+
ret(*_##name) args = nullptr
20+
21+
DECLARE_TYPES(int,
22+
AHardwareBuffer_allocate,
23+
(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer));
24+
DECLARE_TYPES(int,
25+
AHardwareBuffer_isSupported,
26+
(const AHardwareBuffer_Desc* desc));
27+
DECLARE_TYPES(AHardwareBuffer*,
28+
AHardwareBuffer_fromHardwareBuffer,
29+
(JNIEnv * env, jobject hardwareBufferObj));
30+
DECLARE_TYPES(void, AHardwareBuffer_release, (AHardwareBuffer * buffer));
31+
DECLARE_TYPES(void,
32+
AHardwareBuffer_describe,
33+
(AHardwareBuffer * buffer, AHardwareBuffer_Desc* desc));
34+
DECLARE_TYPES(int,
35+
AHardwareBuffer_getId,
36+
(AHardwareBuffer * buffer, uint64_t* outId));
37+
38+
DECLARE_TYPES(bool, ATrace_isEnabled, (void));
39+
40+
DECLARE_TYPES(ASurfaceControl*,
41+
ASurfaceControl_createFromWindow,
42+
(ANativeWindow * parent, const char* debug_name));
43+
DECLARE_TYPES(void,
44+
ASurfaceControl_release,
45+
(ASurfaceControl * surface_control));
46+
DECLARE_TYPES(ASurfaceTransaction*, ASurfaceTransaction_create, (void));
47+
DECLARE_TYPES(void,
48+
ASurfaceTransaction_delete,
49+
(ASurfaceTransaction * surface_transaction));
50+
DECLARE_TYPES(void,
51+
ASurfaceTransaction_apply,
52+
(ASurfaceTransaction * surface_transaction));
53+
DECLARE_TYPES(void,
54+
ASurfaceTransaction_setBuffer,
55+
(ASurfaceTransaction * transaction,
56+
ASurfaceControl* surface_control,
57+
AHardwareBuffer* buffer,
58+
int acquire_fence_fd));
59+
60+
DECLARE_TYPES(AChoreographer*, AChoreographer_getInstance, (void));
61+
DECLARE_TYPES(void,
62+
AChoreographer_postFrameCallback,
63+
(AChoreographer * choreographer,
64+
AChoreographer_frameCallback callbackk,
65+
void* data));
66+
DECLARE_TYPES(void,
67+
AChoreographer_postFrameCallback64,
68+
(AChoreographer * choreographer,
69+
AChoreographer_frameCallback64 callbackk,
70+
void* data));
71+
72+
DECLARE_TYPES(EGLClientBuffer,
73+
eglGetNativeClientBufferANDROID,
74+
(AHardwareBuffer * buffer));
75+
76+
#undef DECLARE_TYPES
77+
78+
std::once_flag init_once;
79+
80+
void InitOnceCallback() {
81+
static fml::RefPtr<fml::NativeLibrary> android =
82+
fml::NativeLibrary::Create("libandroid.so");
83+
FML_CHECK(android.get() != nullptr);
84+
static fml::RefPtr<fml::NativeLibrary> egl =
85+
fml::NativeLibrary::Create("libEGL.so");
86+
FML_CHECK(egl.get() != nullptr);
87+
88+
#define LOOKUP(lib, func) \
89+
_##func = lib->ResolveFunction<fp_##func>(#func).value_or(nullptr)
90+
91+
LOOKUP(egl, eglGetNativeClientBufferANDROID);
92+
93+
LOOKUP(android, AHardwareBuffer_fromHardwareBuffer);
94+
LOOKUP(android, AHardwareBuffer_release);
95+
LOOKUP(android, AHardwareBuffer_getId);
96+
LOOKUP(android, AHardwareBuffer_describe);
97+
LOOKUP(android, AHardwareBuffer_allocate);
98+
LOOKUP(android, AHardwareBuffer_isSupported);
99+
LOOKUP(android, ATrace_isEnabled);
100+
LOOKUP(android, AChoreographer_getInstance);
101+
if (_AChoreographer_getInstance) {
102+
LOOKUP(android, AChoreographer_postFrameCallback64);
103+
if (!_AChoreographer_postFrameCallback64) {
104+
LOOKUP(android, AChoreographer_postFrameCallback);
105+
}
106+
}
107+
108+
LOOKUP(android, ASurfaceControl_createFromWindow);
109+
LOOKUP(android, ASurfaceControl_release);
110+
LOOKUP(android, ASurfaceTransaction_apply);
111+
LOOKUP(android, ASurfaceTransaction_create);
112+
LOOKUP(android, ASurfaceTransaction_delete);
113+
LOOKUP(android, ASurfaceTransaction_setBuffer);
114+
#undef LOOKUP
115+
}
116+
117+
} // namespace
118+
119+
void NDKHelpers::Init() {
120+
std::call_once(init_once, InitOnceCallback);
121+
}
122+
123+
bool NDKHelpers::ATrace_isEnabled() {
124+
if (_ATrace_isEnabled) {
125+
return _ATrace_isEnabled();
126+
}
127+
return false;
128+
}
129+
130+
ChoreographerSupportStatus NDKHelpers::ChoreographerSupported() {
131+
if (_AChoreographer_postFrameCallback64) {
132+
return ChoreographerSupportStatus::kSupported64;
133+
}
134+
if (_AChoreographer_postFrameCallback) {
135+
return ChoreographerSupportStatus::kSupported32;
136+
}
137+
return ChoreographerSupportStatus::kUnsupported;
138+
}
139+
140+
AChoreographer* NDKHelpers::AChoreographer_getInstance() {
141+
FML_CHECK(_AChoreographer_getInstance);
142+
return _AChoreographer_getInstance();
143+
}
144+
145+
void NDKHelpers::AChoreographer_postFrameCallback(
146+
AChoreographer* choreographer,
147+
AChoreographer_frameCallback callback,
148+
void* data) {
149+
FML_CHECK(_AChoreographer_postFrameCallback);
150+
return _AChoreographer_postFrameCallback(choreographer, callback, data);
151+
}
152+
153+
void NDKHelpers::AChoreographer_postFrameCallback64(
154+
AChoreographer* choreographer,
155+
AChoreographer_frameCallback64 callback,
156+
void* data) {
157+
FML_CHECK(_AChoreographer_postFrameCallback64);
158+
return _AChoreographer_postFrameCallback64(choreographer, callback, data);
159+
}
160+
161+
bool NDKHelpers::HardwareBufferSupported() {
162+
const bool r = _AHardwareBuffer_fromHardwareBuffer != nullptr;
163+
return r;
164+
}
165+
166+
AHardwareBuffer* NDKHelpers::AHardwareBuffer_fromHardwareBuffer(
167+
JNIEnv* env,
168+
jobject hardwareBufferObj) {
169+
FML_CHECK(_AHardwareBuffer_fromHardwareBuffer != nullptr);
170+
return _AHardwareBuffer_fromHardwareBuffer(env, hardwareBufferObj);
171+
}
172+
173+
void NDKHelpers::AHardwareBuffer_release(AHardwareBuffer* buffer) {
174+
FML_CHECK(_AHardwareBuffer_release != nullptr);
175+
_AHardwareBuffer_release(buffer);
176+
}
177+
178+
void NDKHelpers::AHardwareBuffer_describe(AHardwareBuffer* buffer,
179+
AHardwareBuffer_Desc* desc) {
180+
FML_CHECK(_AHardwareBuffer_describe != nullptr);
181+
_AHardwareBuffer_describe(buffer, desc);
182+
}
183+
184+
std::optional<HardwareBufferKey> NDKHelpers::AHardwareBuffer_getId(
185+
AHardwareBuffer* buffer) {
186+
if (_AHardwareBuffer_getId == nullptr) {
187+
return std::nullopt;
188+
}
189+
HardwareBufferKey outId;
190+
int result = _AHardwareBuffer_getId(buffer, &outId);
191+
if (result == 0) {
192+
return outId;
193+
}
194+
return std::nullopt;
195+
}
196+
197+
EGLClientBuffer NDKHelpers::eglGetNativeClientBufferANDROID(
198+
AHardwareBuffer* buffer) {
199+
FML_CHECK(_eglGetNativeClientBufferANDROID != nullptr);
200+
return _eglGetNativeClientBufferANDROID(buffer);
201+
}
202+
203+
bool NDKHelpers::SurfaceControlAndTransactionSupported() {
204+
return _ASurfaceControl_createFromWindow && _ASurfaceControl_release &&
205+
_ASurfaceTransaction_create && _ASurfaceTransaction_apply &&
206+
_ASurfaceTransaction_delete && _ASurfaceTransaction_setBuffer;
207+
}
208+
209+
ASurfaceControl* NDKHelpers::ASurfaceControl_createFromWindow(
210+
ANativeWindow* parent,
211+
const char* debug_name) {
212+
FML_CHECK(_ASurfaceControl_createFromWindow);
213+
return _ASurfaceControl_createFromWindow(parent, debug_name);
214+
}
215+
216+
void NDKHelpers::ASurfaceControl_release(ASurfaceControl* surface_control) {
217+
FML_CHECK(_ASurfaceControl_release);
218+
return _ASurfaceControl_release(surface_control);
219+
}
220+
221+
ASurfaceTransaction* NDKHelpers::ASurfaceTransaction_create() {
222+
FML_CHECK(_ASurfaceTransaction_create);
223+
return _ASurfaceTransaction_create();
224+
}
225+
226+
void NDKHelpers::ASurfaceTransaction_delete(
227+
ASurfaceTransaction* surface_transaction) {
228+
FML_CHECK(_ASurfaceTransaction_delete);
229+
_ASurfaceTransaction_delete(surface_transaction);
230+
}
231+
232+
void NDKHelpers::ASurfaceTransaction_apply(
233+
ASurfaceTransaction* surface_transaction) {
234+
FML_CHECK(_ASurfaceTransaction_apply);
235+
_ASurfaceTransaction_apply(surface_transaction);
236+
}
237+
238+
void NDKHelpers::ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
239+
ASurfaceControl* surface_control,
240+
AHardwareBuffer* buffer,
241+
int acquire_fence_fd) {
242+
FML_CHECK(_ASurfaceTransaction_setBuffer);
243+
_ASurfaceTransaction_setBuffer(transaction, surface_control, buffer,
244+
acquire_fence_fd);
245+
}
246+
247+
int NDKHelpers::AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) {
248+
FML_CHECK(_AHardwareBuffer_isSupported);
249+
return _AHardwareBuffer_isSupported(desc);
250+
}
251+
252+
int NDKHelpers::AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
253+
AHardwareBuffer** outBuffer) {
254+
FML_CHECK(_AHardwareBuffer_allocate);
255+
return _AHardwareBuffer_allocate(desc, outBuffer);
256+
}
257+
258+
} // namespace flutter

0 commit comments

Comments
 (0)