1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "nativebridge"
18
19 #include "nativebridge/native_bridge.h"
20
21 #include <dlfcn.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <sys/mount.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28
29 #include <cstring>
30
31 #include <android-base/macros.h>
32 #include <log/log.h>
33
34 #ifdef ART_TARGET_ANDROID
35 #include "nativeloader/dlext_namespaces.h"
36 #endif
37
38 namespace android {
39
40 #ifdef __APPLE__
41 template <typename T>
UNUSED(const T &)42 void UNUSED(const T&) {}
43 #endif
44
45 extern "C" {
46
OpenSystemLibrary(const char * path,int flags)47 void* OpenSystemLibrary(const char* path, int flags) {
48 #ifdef ART_TARGET_ANDROID
49 // The system namespace is called "default" for binaries in /system and
50 // "system" for those in the Runtime APEX. Try "system" first since
51 // "default" always exists.
52 // TODO(b/185587109): Get rid of this error prone logic.
53 android_namespace_t* system_ns = android_get_exported_namespace("system");
54 if (system_ns == nullptr) {
55 system_ns = android_get_exported_namespace("default");
56 LOG_ALWAYS_FATAL_IF(system_ns == nullptr,
57 "Failed to get system namespace for loading %s", path);
58 }
59 const android_dlextinfo dlextinfo = {
60 .flags = ANDROID_DLEXT_USE_NAMESPACE,
61 .library_namespace = system_ns,
62 };
63 return android_dlopen_ext(path, flags, &dlextinfo);
64 #else
65 return dlopen(path, flags);
66 #endif
67 }
68
69 // Environment values required by the apps running with native bridge.
70 struct NativeBridgeRuntimeValues {
71 const char* os_arch;
72 const char* cpu_abi;
73 const char* cpu_abi2;
74 const char* *supported_abis;
75 int32_t abi_count;
76 };
77
78 // The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks.
79 static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf";
80
81 enum class NativeBridgeState {
82 kNotSetup, // Initial state.
83 kOpened, // After successful dlopen.
84 kPreInitialized, // After successful pre-initialization.
85 kInitialized, // After successful initialization.
86 kClosed // Closed or errors.
87 };
88
89 static constexpr const char* kNotSetupString = "kNotSetup";
90 static constexpr const char* kOpenedString = "kOpened";
91 static constexpr const char* kPreInitializedString = "kPreInitialized";
92 static constexpr const char* kInitializedString = "kInitialized";
93 static constexpr const char* kClosedString = "kClosed";
94
GetNativeBridgeStateString(NativeBridgeState state)95 static const char* GetNativeBridgeStateString(NativeBridgeState state) {
96 switch (state) {
97 case NativeBridgeState::kNotSetup:
98 return kNotSetupString;
99
100 case NativeBridgeState::kOpened:
101 return kOpenedString;
102
103 case NativeBridgeState::kPreInitialized:
104 return kPreInitializedString;
105
106 case NativeBridgeState::kInitialized:
107 return kInitializedString;
108
109 case NativeBridgeState::kClosed:
110 return kClosedString;
111 }
112 }
113
114 // Current state of the native bridge.
115 static NativeBridgeState state = NativeBridgeState::kNotSetup;
116
117 // The version of NativeBridge implementation.
118 // Different Nativebridge interface needs the service of different version of
119 // Nativebridge implementation.
120 // Used by isCompatibleWith() which is introduced in v2.
121 enum NativeBridgeImplementationVersion {
122 // first version, not used.
123 DEFAULT_VERSION = 1,
124 // The version which signal semantic is introduced.
125 SIGNAL_VERSION = 2,
126 // The version which namespace semantic is introduced.
127 NAMESPACE_VERSION = 3,
128 // The version with vendor namespaces
129 VENDOR_NAMESPACE_VERSION = 4,
130 // The version with runtime namespaces
131 RUNTIME_NAMESPACE_VERSION = 5,
132 // The version with pre-zygote-fork hook to support app-zygotes.
133 PRE_ZYGOTE_FORK_VERSION = 6,
134 // The version with critical_native support
135 CRITICAL_NATIVE_SUPPORT_VERSION = 7,
136 // The version with native bridge detection fallback for function pointers
137 IDENTIFY_NATIVELY_BRIDGED_FUNCTION_POINTERS_VERSION = 8,
138 };
139
140 // Whether we had an error at some point.
141 static bool had_error = false;
142
143 // Handle of the loaded library.
144 static void* native_bridge_handle = nullptr;
145 // Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized
146 // later.
147 static const NativeBridgeCallbacks* callbacks = nullptr;
148 // Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge.
149 static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr;
150
151 // The app's code cache directory.
152 static char* app_code_cache_dir = nullptr;
153
154 // Code cache directory (relative to the application private directory)
155 // Ideally we'd like to call into framework to retrieve this name. However that's considered an
156 // implementation detail and will require either hacks or consistent refactorings. We compromise
157 // and hard code the directory name again here.
158 static constexpr const char* kCodeCacheDir = "code_cache";
159
160 // Characters allowed in a native bridge filename. The first character must
161 // be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-].
CharacterAllowed(char c,bool first)162 static bool CharacterAllowed(char c, bool first) {
163 if (first) {
164 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
165 } else {
166 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
167 (c == '.') || (c == '_') || (c == '-');
168 }
169 }
170
ReleaseAppCodeCacheDir()171 static void ReleaseAppCodeCacheDir() {
172 if (app_code_cache_dir != nullptr) {
173 delete[] app_code_cache_dir;
174 app_code_cache_dir = nullptr;
175 }
176 }
177
178 // We only allow simple names for the library. It is supposed to be a file in
179 // /system/lib or /vendor/lib. Only allow a small range of characters, that is
180 // names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z].
NativeBridgeNameAcceptable(const char * nb_library_filename)181 bool NativeBridgeNameAcceptable(const char* nb_library_filename) {
182 const char* ptr = nb_library_filename;
183 if (*ptr == 0) {
184 // Emptry string. Allowed, means no native bridge.
185 return true;
186 } else {
187 // First character must be [a-zA-Z].
188 if (!CharacterAllowed(*ptr, true)) {
189 // Found an invalid fist character, don't accept.
190 ALOGE("Native bridge library %s has been rejected for first character %c",
191 nb_library_filename,
192 *ptr);
193 return false;
194 } else {
195 // For the rest, be more liberal.
196 ptr++;
197 while (*ptr != 0) {
198 if (!CharacterAllowed(*ptr, false)) {
199 // Found an invalid character, don't accept.
200 ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr);
201 return false;
202 }
203 ptr++;
204 }
205 }
206 return true;
207 }
208 }
209
210 // The policy of invoking Nativebridge changed in v3 with/without namespace.
211 // Suggest Nativebridge implementation not maintain backward-compatible.
isCompatibleWith(const uint32_t version)212 static bool isCompatibleWith(const uint32_t version) {
213 // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported
214 // version.
215 if (callbacks == nullptr || callbacks->version == 0 || version == 0) {
216 return false;
217 }
218
219 // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check.
220 if (callbacks->version >= SIGNAL_VERSION) {
221 return callbacks->isCompatibleWith(version);
222 }
223
224 return true;
225 }
226
CloseNativeBridge(bool with_error)227 static void CloseNativeBridge(bool with_error) {
228 state = NativeBridgeState::kClosed;
229 had_error |= with_error;
230 ReleaseAppCodeCacheDir();
231 }
232
LoadNativeBridge(const char * nb_library_filename,const NativeBridgeRuntimeCallbacks * runtime_cbs)233 bool LoadNativeBridge(const char* nb_library_filename,
234 const NativeBridgeRuntimeCallbacks* runtime_cbs) {
235 // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not
236 // multi-threaded, so we do not need locking here.
237
238 if (state != NativeBridgeState::kNotSetup) {
239 // Setup has been called before. Ignore this call.
240 if (nb_library_filename != nullptr) { // Avoids some log-spam for dalvikvm.
241 ALOGW("Called LoadNativeBridge for an already set up native bridge. State is %s.",
242 GetNativeBridgeStateString(state));
243 }
244 // Note: counts as an error, even though the bridge may be functional.
245 had_error = true;
246 return false;
247 }
248
249 if (nb_library_filename == nullptr || *nb_library_filename == 0) {
250 CloseNativeBridge(false);
251 return false;
252 } else {
253 if (!NativeBridgeNameAcceptable(nb_library_filename)) {
254 CloseNativeBridge(true);
255 } else {
256 // Try to open the library. We assume this library is provided by the
257 // platform rather than the ART APEX itself, so use the system namespace
258 // to avoid requiring a static linker config link to it from the
259 // com_android_art namespace.
260 void* handle = OpenSystemLibrary(nb_library_filename, RTLD_LAZY);
261
262 if (handle != nullptr) {
263 callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
264 kNativeBridgeInterfaceSymbol));
265 if (callbacks != nullptr) {
266 if (isCompatibleWith(NAMESPACE_VERSION)) {
267 // Store the handle for later.
268 native_bridge_handle = handle;
269 } else {
270 ALOGW("Unsupported native bridge API in %s (is version %d not compatible with %d)",
271 nb_library_filename, callbacks->version, NAMESPACE_VERSION);
272 callbacks = nullptr;
273 dlclose(handle);
274 }
275 } else {
276 dlclose(handle);
277 ALOGW("Unsupported native bridge API in %s: %s not found",
278 nb_library_filename, kNativeBridgeInterfaceSymbol);
279 }
280 } else {
281 ALOGW("Failed to load native bridge implementation: %s", dlerror());
282 }
283
284 // Two failure conditions: could not find library (dlopen failed), or could not find native
285 // bridge interface (dlsym failed). Both are an error and close the native bridge.
286 if (callbacks == nullptr) {
287 CloseNativeBridge(true);
288 } else {
289 runtime_callbacks = runtime_cbs;
290 state = NativeBridgeState::kOpened;
291 }
292 }
293 return state == NativeBridgeState::kOpened;
294 }
295 }
296
NeedsNativeBridge(const char * instruction_set)297 bool NeedsNativeBridge(const char* instruction_set) {
298 if (instruction_set == nullptr) {
299 ALOGE("Null instruction set in NeedsNativeBridge.");
300 return false;
301 }
302 return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0;
303 }
304
305 #ifndef __APPLE__
MountCpuinfo(const char * cpuinfo_path)306 static bool MountCpuinfo(const char* cpuinfo_path) {
307 // If the file does not exist, the mount command will fail,
308 // so we save the extra file existence check.
309 if (TEMP_FAILURE_RETRY(mount(cpuinfo_path, // Source.
310 "/proc/cpuinfo", // Target.
311 nullptr, // FS type.
312 MS_BIND, // Mount flags: bind mount.
313 nullptr)) == -1) { // "Data."
314 ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno));
315 return false;
316 }
317 return true;
318 }
319 #endif
320
MountCpuinfoForInstructionSet(const char * instruction_set)321 static void MountCpuinfoForInstructionSet(const char* instruction_set) {
322 if (instruction_set == nullptr) {
323 return;
324 }
325
326 size_t isa_len = strlen(instruction_set);
327 if (isa_len > 10) {
328 // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for
329 // x86_64 [including the trailing \0]). This is so we don't have to change here if there will
330 // be another instruction set in the future.
331 ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.",
332 instruction_set);
333 return;
334 }
335
336 #if defined(__APPLE__)
337 ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible.");
338
339 #elif !defined(__ANDROID__)
340 // To be able to test on the host, we hardwire a relative path.
341 MountCpuinfo("./cpuinfo");
342
343 #else // __ANDROID__
344 char cpuinfo_path[1024];
345
346 // Bind-mount /system/etc/cpuinfo.<isa>.txt to /proc/cpuinfo.
347 snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/etc/cpuinfo.%s.txt", instruction_set);
348 if (MountCpuinfo(cpuinfo_path)) {
349 return;
350 }
351
352 // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo.
353 // TODO(b/179753190): remove when all implementations migrate to system/etc!
354 #ifdef __LP64__
355 snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib64/%s/cpuinfo", instruction_set);
356 #else
357 snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib/%s/cpuinfo", instruction_set);
358 #endif // __LP64__
359 MountCpuinfo(cpuinfo_path);
360
361 #endif
362 }
363
PreInitializeNativeBridge(const char * app_data_dir_in,const char * instruction_set)364 bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
365 if (state != NativeBridgeState::kOpened) {
366 ALOGE("Invalid state: native bridge is expected to be opened.");
367 CloseNativeBridge(true);
368 return false;
369 }
370
371 if (app_data_dir_in != nullptr) {
372 // Create the path to the application code cache directory.
373 // The memory will be release after Initialization or when the native bridge is closed.
374 const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/'
375 app_code_cache_dir = new char[len];
376 snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir);
377 } else {
378 ALOGW("Application private directory isn't available.");
379 app_code_cache_dir = nullptr;
380 }
381
382 // Mount cpuinfo that corresponds to the instruction set.
383 // Failure is not fatal.
384 MountCpuinfoForInstructionSet(instruction_set);
385
386 state = NativeBridgeState::kPreInitialized;
387 return true;
388 }
389
PreZygoteForkNativeBridge()390 void PreZygoteForkNativeBridge() {
391 if (NativeBridgeInitialized()) {
392 if (isCompatibleWith(PRE_ZYGOTE_FORK_VERSION)) {
393 return callbacks->preZygoteFork();
394 } else {
395 ALOGE("not compatible with version %d, preZygoteFork() isn't invoked",
396 PRE_ZYGOTE_FORK_VERSION);
397 }
398 }
399 }
400
SetCpuAbi(JNIEnv * env,jclass build_class,const char * field,const char * value)401 static void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) {
402 if (value != nullptr) {
403 jfieldID field_id = env->GetStaticFieldID(build_class, field, "Ljava/lang/String;");
404 if (field_id == nullptr) {
405 env->ExceptionClear();
406 ALOGW("Could not find %s field.", field);
407 return;
408 }
409
410 jstring str = env->NewStringUTF(value);
411 if (str == nullptr) {
412 env->ExceptionClear();
413 ALOGW("Could not create string %s.", value);
414 return;
415 }
416
417 env->SetStaticObjectField(build_class, field_id, str);
418 }
419 }
420
421 // Set up the environment for the bridged app.
SetupEnvironment(const NativeBridgeCallbacks * cbs,JNIEnv * env,const char * isa)422 static void SetupEnvironment(const NativeBridgeCallbacks* cbs, JNIEnv* env, const char* isa) {
423 // Need a JNIEnv* to do anything.
424 if (env == nullptr) {
425 ALOGW("No JNIEnv* to set up app environment.");
426 return;
427 }
428
429 // Query the bridge for environment values.
430 const struct NativeBridgeRuntimeValues* env_values = cbs->getAppEnv(isa);
431 if (env_values == nullptr) {
432 return;
433 }
434
435 // Keep the JNIEnv clean.
436 jint success = env->PushLocalFrame(16); // That should be small and large enough.
437 if (success < 0) {
438 // Out of memory, really borked.
439 ALOGW("Out of memory while setting up app environment.");
440 env->ExceptionClear();
441 return;
442 }
443
444 // Reset CPU_ABI & CPU_ABI2 to values required by the apps running with native bridge.
445 if (env_values->cpu_abi != nullptr || env_values->cpu_abi2 != nullptr ||
446 env_values->abi_count >= 0) {
447 jclass bclass_id = env->FindClass("android/os/Build");
448 if (bclass_id != nullptr) {
449 SetCpuAbi(env, bclass_id, "CPU_ABI", env_values->cpu_abi);
450 SetCpuAbi(env, bclass_id, "CPU_ABI2", env_values->cpu_abi2);
451 } else {
452 // For example in a host test environment.
453 env->ExceptionClear();
454 ALOGW("Could not find Build class.");
455 }
456 }
457
458 if (env_values->os_arch != nullptr) {
459 jclass sclass_id = env->FindClass("java/lang/System");
460 if (sclass_id != nullptr) {
461 jmethodID set_prop_id = env->GetStaticMethodID(sclass_id, "setUnchangeableSystemProperty",
462 "(Ljava/lang/String;Ljava/lang/String;)V");
463 if (set_prop_id != nullptr) {
464 // Init os.arch to the value reqired by the apps running with native bridge.
465 env->CallStaticVoidMethod(sclass_id, set_prop_id, env->NewStringUTF("os.arch"),
466 env->NewStringUTF(env_values->os_arch));
467 } else {
468 env->ExceptionClear();
469 ALOGW("Could not find System#setUnchangeableSystemProperty.");
470 }
471 } else {
472 env->ExceptionClear();
473 ALOGW("Could not find System class.");
474 }
475 }
476
477 // Make it pristine again.
478 env->PopLocalFrame(nullptr);
479 }
480
InitializeNativeBridge(JNIEnv * env,const char * instruction_set)481 bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
482 // We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that
483 // point we are not multi-threaded, so we do not need locking here.
484
485 if (state == NativeBridgeState::kPreInitialized) {
486 if (app_code_cache_dir != nullptr) {
487 // Check for code cache: if it doesn't exist try to create it.
488 struct stat st;
489 if (stat(app_code_cache_dir, &st) == -1) {
490 if (errno == ENOENT) {
491 if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) {
492 ALOGW("Cannot create code cache directory %s: %s.",
493 app_code_cache_dir, strerror(errno));
494 ReleaseAppCodeCacheDir();
495 }
496 } else {
497 ALOGW("Cannot stat code cache directory %s: %s.",
498 app_code_cache_dir, strerror(errno));
499 ReleaseAppCodeCacheDir();
500 }
501 } else if (!S_ISDIR(st.st_mode)) {
502 ALOGW("Code cache is not a directory %s.", app_code_cache_dir);
503 ReleaseAppCodeCacheDir();
504 }
505 }
506
507 // If we're still PreInitialized (didn't fail the code cache checks) try to initialize.
508 if (state == NativeBridgeState::kPreInitialized) {
509 if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) {
510 SetupEnvironment(callbacks, env, instruction_set);
511 state = NativeBridgeState::kInitialized;
512 // We no longer need the code cache path, release the memory.
513 ReleaseAppCodeCacheDir();
514 } else {
515 // Unload the library.
516 dlclose(native_bridge_handle);
517 CloseNativeBridge(true);
518 }
519 }
520 } else {
521 CloseNativeBridge(true);
522 }
523
524 return state == NativeBridgeState::kInitialized;
525 }
526
UnloadNativeBridge()527 void UnloadNativeBridge() {
528 // We expect only one place that calls UnloadNativeBridge: Runtime::DidForkFromZygote. At that
529 // point we are not multi-threaded, so we do not need locking here.
530
531 switch (state) {
532 case NativeBridgeState::kOpened:
533 case NativeBridgeState::kPreInitialized:
534 case NativeBridgeState::kInitialized:
535 // Unload.
536 dlclose(native_bridge_handle);
537 CloseNativeBridge(false);
538 break;
539
540 case NativeBridgeState::kNotSetup:
541 // Not even set up. Error.
542 CloseNativeBridge(true);
543 break;
544
545 case NativeBridgeState::kClosed:
546 // Ignore.
547 break;
548 }
549 }
550
NativeBridgeError()551 bool NativeBridgeError() {
552 return had_error;
553 }
554
NativeBridgeAvailable()555 bool NativeBridgeAvailable() {
556 return state == NativeBridgeState::kOpened
557 || state == NativeBridgeState::kPreInitialized
558 || state == NativeBridgeState::kInitialized;
559 }
560
NativeBridgeInitialized()561 bool NativeBridgeInitialized() {
562 // Calls of this are supposed to happen in a state where the native bridge is stable, i.e., after
563 // Runtime::DidForkFromZygote. In that case we do not need a lock.
564 return state == NativeBridgeState::kInitialized;
565 }
566
NativeBridgeLoadLibrary(const char * libpath,int flag)567 void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
568 if (NativeBridgeInitialized()) {
569 return callbacks->loadLibrary(libpath, flag);
570 }
571 return nullptr;
572 }
573
NativeBridgeGetTrampoline(void * handle,const char * name,const char * shorty,uint32_t len)574 void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty,
575 uint32_t len) {
576 return NativeBridgeGetTrampoline2(handle, name, shorty, len, kJNICallTypeRegular);
577 }
578
NativeBridgeGetTrampoline2(void * handle,const char * name,const char * shorty,uint32_t len,JNICallType jni_call_type)579 void* NativeBridgeGetTrampoline2(
580 void* handle, const char* name, const char* shorty, uint32_t len, JNICallType jni_call_type) {
581 if (!NativeBridgeInitialized()) {
582 return nullptr;
583 }
584
585 // For version 1 isCompatibleWith is always true, even though the extensions
586 // are not supported, so we need to handle it separately.
587 if (callbacks != nullptr && callbacks->version == DEFAULT_VERSION) {
588 return callbacks->getTrampoline(handle, name, shorty, len);
589 }
590
591 if (isCompatibleWith(CRITICAL_NATIVE_SUPPORT_VERSION)) {
592 return callbacks->getTrampolineWithJNICallType(handle, name, shorty, len, jni_call_type);
593 }
594
595 return callbacks->getTrampoline(handle, name, shorty, len);
596 }
597
NativeBridgeGetTrampolineForFunctionPointer(const void * method,const char * shorty,uint32_t len,JNICallType jni_call_type)598 void* NativeBridgeGetTrampolineForFunctionPointer(const void* method,
599 const char* shorty,
600 uint32_t len,
601 JNICallType jni_call_type) {
602 if (!NativeBridgeInitialized()) {
603 return nullptr;
604 }
605
606 if (isCompatibleWith(CRITICAL_NATIVE_SUPPORT_VERSION)) {
607 return callbacks->getTrampolineForFunctionPointer(method, shorty, len, jni_call_type);
608 } else {
609 ALOGE("not compatible with version %d, getTrampolineFnPtrWithJNICallType() isn't invoked",
610 CRITICAL_NATIVE_SUPPORT_VERSION);
611 return nullptr;
612 }
613 }
614
NativeBridgeIsSupported(const char * libpath)615 bool NativeBridgeIsSupported(const char* libpath) {
616 if (NativeBridgeInitialized()) {
617 return callbacks->isSupported(libpath);
618 }
619 return false;
620 }
621
NativeBridgeGetVersion()622 uint32_t NativeBridgeGetVersion() {
623 if (NativeBridgeAvailable()) {
624 return callbacks->version;
625 }
626 return 0;
627 }
628
NativeBridgeGetSignalHandler(int signal)629 NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
630 if (NativeBridgeInitialized()) {
631 if (isCompatibleWith(SIGNAL_VERSION)) {
632 return callbacks->getSignalHandler(signal);
633 } else {
634 ALOGE("not compatible with version %d, cannot get signal handler", SIGNAL_VERSION);
635 }
636 }
637 return nullptr;
638 }
639
NativeBridgeUnloadLibrary(void * handle)640 int NativeBridgeUnloadLibrary(void* handle) {
641 if (NativeBridgeInitialized()) {
642 if (isCompatibleWith(NAMESPACE_VERSION)) {
643 return callbacks->unloadLibrary(handle);
644 } else {
645 ALOGE("not compatible with version %d, cannot unload library", NAMESPACE_VERSION);
646 }
647 }
648 return -1;
649 }
650
NativeBridgeGetError()651 const char* NativeBridgeGetError() {
652 if (NativeBridgeInitialized()) {
653 if (isCompatibleWith(NAMESPACE_VERSION)) {
654 return callbacks->getError();
655 } else {
656 return "native bridge implementation is not compatible with version 3, cannot get message";
657 }
658 }
659 return "native bridge is not initialized";
660 }
661
NativeBridgeIsPathSupported(const char * path)662 bool NativeBridgeIsPathSupported(const char* path) {
663 if (NativeBridgeInitialized()) {
664 if (isCompatibleWith(NAMESPACE_VERSION)) {
665 return callbacks->isPathSupported(path);
666 } else {
667 ALOGE("not compatible with version %d, cannot check via library path", NAMESPACE_VERSION);
668 }
669 }
670 return false;
671 }
672
NativeBridgeCreateNamespace(const char * name,const char * ld_library_path,const char * default_library_path,uint64_t type,const char * permitted_when_isolated_path,native_bridge_namespace_t * parent_ns)673 native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
674 const char* ld_library_path,
675 const char* default_library_path,
676 uint64_t type,
677 const char* permitted_when_isolated_path,
678 native_bridge_namespace_t* parent_ns) {
679 if (NativeBridgeInitialized()) {
680 if (isCompatibleWith(NAMESPACE_VERSION)) {
681 return callbacks->createNamespace(name,
682 ld_library_path,
683 default_library_path,
684 type,
685 permitted_when_isolated_path,
686 parent_ns);
687 } else {
688 ALOGE("not compatible with version %d, cannot create namespace %s", NAMESPACE_VERSION, name);
689 }
690 }
691
692 return nullptr;
693 }
694
NativeBridgeLinkNamespaces(native_bridge_namespace_t * from,native_bridge_namespace_t * to,const char * shared_libs_sonames)695 bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
696 const char* shared_libs_sonames) {
697 if (NativeBridgeInitialized()) {
698 if (isCompatibleWith(NAMESPACE_VERSION)) {
699 return callbacks->linkNamespaces(from, to, shared_libs_sonames);
700 } else {
701 ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
702 }
703 }
704
705 return false;
706 }
707
NativeBridgeGetExportedNamespace(const char * name)708 native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
709 if (!NativeBridgeInitialized()) {
710 return nullptr;
711 }
712
713 if (isCompatibleWith(RUNTIME_NAMESPACE_VERSION)) {
714 return callbacks->getExportedNamespace(name);
715 }
716
717 // sphal is vendor namespace name -> use v4 callback in the case NB callbacks
718 // are not compatible with v5
719 if (isCompatibleWith(VENDOR_NAMESPACE_VERSION) && name != nullptr && strcmp("sphal", name) == 0) {
720 return callbacks->getVendorNamespace();
721 }
722
723 return nullptr;
724 }
725
NativeBridgeLoadLibraryExt(const char * libpath,int flag,native_bridge_namespace_t * ns)726 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
727 if (NativeBridgeInitialized()) {
728 if (isCompatibleWith(NAMESPACE_VERSION)) {
729 return callbacks->loadLibraryExt(libpath, flag, ns);
730 } else {
731 ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION);
732 }
733 }
734 return nullptr;
735 }
736
NativeBridgeIsNativeBridgeFunctionPointer(const void * method)737 bool NativeBridgeIsNativeBridgeFunctionPointer(const void* method) {
738 if (NativeBridgeInitialized()) {
739 if (isCompatibleWith(IDENTIFY_NATIVELY_BRIDGED_FUNCTION_POINTERS_VERSION)) {
740 return callbacks->isNativeBridgeFunctionPointer(method);
741 } else {
742 ALOGW("not compatible with version %d, unable to call isNativeBridgeFunctionPointer",
743 IDENTIFY_NATIVELY_BRIDGED_FUNCTION_POINTERS_VERSION);
744 }
745 }
746 return false;
747 }
748
749 } // extern "C"
750
751 } // namespace android
752