LibNativeBridge: Version 2
Add a callback function to retrieve "signal handler" from the bridge,
if the bridge wants it to be managed by the runtime. The signal handler
will be invoked after the runtime's own one, and before any other
chained handler.
Add a callback function to check compatibility of the bridge with the
library.
Add a function to expose the native bridge version. Add a test for this
function.
Bug: 20217701
(cherry picked from commit a6ac9ce98bd38099a4e89010111d14e4d5fc190e)
Change-Id: Ic23a60b949f119c7d8b0e7cb27a61e6c16532a23
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 6fa4b39..f63497b 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -83,7 +83,7 @@
static void* native_bridge_handle = nullptr;
// Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized
// later.
-static NativeBridgeCallbacks* callbacks = nullptr;
+static const NativeBridgeCallbacks* callbacks = nullptr;
// Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge.
static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr;
@@ -96,7 +96,7 @@
// and hard code the directory name again here.
static constexpr const char* kCodeCacheDir = "code_cache";
-static constexpr uint32_t kNativeBridgeCallbackVersion = 1;
+static constexpr uint32_t kLibNativeBridgeVersion = 2;
// Characters allowed in a native bridge filename. The first character must
// be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-].
@@ -121,7 +121,9 @@
// First character must be [a-zA-Z].
if (!CharacterAllowed(*ptr, true)) {
// Found an invalid fist character, don't accept.
- ALOGE("Native bridge library %s has been rejected for first character %c", nb_library_filename, *ptr);
+ ALOGE("Native bridge library %s has been rejected for first character %c",
+ nb_library_filename,
+ *ptr);
return false;
} else {
// For the rest, be more liberal.
@@ -139,8 +141,22 @@
}
}
-static bool VersionCheck(NativeBridgeCallbacks* cb) {
- return cb != nullptr && cb->version == kNativeBridgeCallbackVersion;
+static bool VersionCheck(const NativeBridgeCallbacks* cb) {
+ // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported
+ // version.
+ if (cb == nullptr || cb->version == 0) {
+ return false;
+ }
+
+ // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check.
+ if (cb->version >= 2) {
+ if (!callbacks->isCompatibleWith(kLibNativeBridgeVersion)) {
+ // TODO: Scan which version is supported, and fall back to handle it.
+ return false;
+ }
+ }
+
+ return true;
}
static void CloseNativeBridge(bool with_error) {
@@ -321,7 +337,7 @@
}
// Set up the environment for the bridged app.
-static void SetupEnvironment(NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) {
+static void SetupEnvironment(const NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) {
// Need a JNIEnv* to do anything.
if (env == nullptr) {
ALOGW("No JNIEnv* to set up app environment.");
@@ -485,4 +501,18 @@
return false;
}
+uint32_t NativeBridgeGetVersion() {
+ if (NativeBridgeAvailable()) {
+ return callbacks->version;
+ }
+ return 0;
+}
+
+NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
+ if (NativeBridgeInitialized() && callbacks->version >= 2) {
+ return callbacks->getSignalHandler(signal);
+ }
+ return nullptr;
+}
+
}; // namespace android