Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8fb11df authored by Zhenhua WANG's avatar Zhenhua WANG Committed by Calin Juravle
Browse files

NativeBridge: add "linked namespace" semantic corresponding to linker

For dynamic linking perspective, semantics of NativeBridge needs to
align with dynamic linker. This patch adds "linked namespace" semantic
which shares some libraries from one namespace to another.

Test: make test-art-host-run-test-115-native-bridge
Change-Id: I71ce1dde19d61363d5eb9731fd4795a8c315b3a0
parent c169b201
Loading
Loading
Loading
Loading
+74 −32
Original line number Diff line number Diff line
@@ -116,14 +116,25 @@ struct native_bridge_namespace_t;
// Use NativeBridgeIsSupported() instead in non-namespace scenario.
bool NativeBridgeIsPathSupported(const char* path);

// Initializes public and anonymous namespace at native bridge side.
// Initializes anonymous namespace.
// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
//
// The anonymous namespace is used in the case when a NativeBridge implementation
// cannot identify the caller of dlopen/dlsym which happens for the code not loaded
// by dynamic linker; for example calls from the mono-compiled code.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
bool NativeBridgeInitNamespace(const char* public_ns_sonames,
bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
                                        const char* anon_ns_library_path);

// Create a namespace and pass the key of related namespaces to native bridge.
// Create new namespace in which native libraries will be loaded.
// NativeBridge's peer of android_create_namespace() of dynamic linker.
//
// The libraries in the namespace are searched by folowing order:
// 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
// 2. In directories specified by DT_RUNPATH of the "needed by" binary.
// 3. deault_library_path (This of this as namespace-local default library path)
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
@@ -134,7 +145,17 @@ native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
                                                       const char* permitted_when_isolated_path,
                                                       native_bridge_namespace_t* parent_ns);

// Creates a link which shares some libraries from one namespace to another.
// NativeBridge's peer of android_link_namespaces() of dynamic linker.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
                                const char* shared_libs_sonames);

// Load a shared library with namespace key that is supported by the native bridge.
// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
// extension.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
@@ -152,7 +173,7 @@ struct NativeBridgeCallbacks {
  // Parameters:
  //   runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
  // Returns:
  //   true iff initialization was successful.
  //   true if initialization was successful.
  bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
                     const char* instruction_set);

@@ -208,7 +229,7 @@ struct NativeBridgeCallbacks {
  // Parameters:
  //   bridge_version [IN] the version of libnativebridge.
  // Returns:
  //     true iff the native bridge supports the given version of libnativebridge.
  //   true if the native bridge supports the given version of libnativebridge.
  bool (*isCompatibleWith)(uint32_t bridge_version);

  // A callback to retrieve a native bridge's signal handler for the specified signal. The runtime
@@ -257,8 +278,12 @@ struct NativeBridgeCallbacks {
  // Use isSupported instead in non-namespace scenario.
  bool (*isPathSupported)(const char* library_path);

  // Initializes anonymous namespace at native bridge side and pass the key of
  // two namespaces(default and anonymous) owned by dynamic linker to native bridge.
  // Initializes anonymous namespace at native bridge side.
  // NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
  //
  // The anonymous namespace is used in the case when a NativeBridge implementation
  // cannot identify the caller of dlopen/dlsym which happens for the code not loaded
  // by dynamic linker; for example calls from the mono-compiled code.
  //
  // Parameters:
  //   public_ns_sonames [IN] the name of "public" libraries.
@@ -269,11 +294,10 @@ struct NativeBridgeCallbacks {
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Should not use in non-namespace scenario.
  bool (*initNamespace)(const char* public_ns_sonames,
                        const char* anon_ns_library_path);

  bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);

  // Create a namespace and pass the key of releated namespaces to native bridge.
  // Create new namespace in which native libraries will be loaded.
  // NativeBridge's peer of android_create_namespace() of dynamic linker.
  //
  // Parameters:
  //   name [IN] the name of the namespace.
@@ -294,7 +318,25 @@ struct NativeBridgeCallbacks {
                                                const char* permitted_when_isolated_path,
                                                native_bridge_namespace_t* parent_ns);

  // Creates a link which shares some libraries from one namespace to another.
  // NativeBridge's peer of android_link_namespaces() of dynamic linker.
  //
  // Parameters:
  //   from [IN] the namespace where libraries are accessed.
  //   to [IN] the namespace where libraries are loaded.
  //   shared_libs_sonames [IN] the libraries to be shared.
  //
  // Returns:
  //   Whether successed or not.
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Should not use in non-namespace scenario.
  bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
                         const char* shared_libs_sonames);

  // Load a shared library within a namespace.
  // NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
  // extension.
  //
  // Parameters:
  //   libpath [IN] path to the shared library
+16 −3
Original line number Diff line number Diff line
@@ -573,11 +573,11 @@ bool NativeBridgeIsPathSupported(const char* path) {
  return false;
}

bool NativeBridgeInitNamespace(const char* public_ns_sonames,
bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
                                        const char* anon_ns_library_path) {
  if (NativeBridgeInitialized()) {
    if (isCompatibleWith(NAMESPACE_VERSION)) {
      return callbacks->initNamespace(public_ns_sonames, anon_ns_library_path);
      return callbacks->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path);
    } else {
      ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
    }
@@ -608,6 +608,19 @@ native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
  return nullptr;
}

bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
                                const char* shared_libs_sonames) {
  if (NativeBridgeInitialized()) {
    if (isCompatibleWith(NAMESPACE_VERSION)) {
      return callbacks->linkNamespaces(from, to, shared_libs_sonames);
    } else {
      ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
    }
  }

  return false;
}

void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
  if (NativeBridgeInitialized()) {
    if (isCompatibleWith(NAMESPACE_VERSION)) {
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ test_src_files := \
    NativeBridge3UnloadLibrary_test.cpp \
    NativeBridge3GetError_test.cpp \
    NativeBridge3IsPathSupported_test.cpp \
    NativeBridge3InitNamespace_test.cpp \
    NativeBridge3InitAnonymousNamespace_test.cpp \
    NativeBridge3CreateNamespace_test.cpp \
    NativeBridge3LoadLibraryExt_test.cpp

+27 −23
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
  return true;
}

extern "C" bool native_bridge3_initNamespace(const char* /* public_ns_sonames */,
extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
                                                      const char* /* anon_ns_library_path */) {
  return true;
}
@@ -91,13 +91,18 @@ native_bridge3_createNamespace(const char* /* name */,
  return nullptr;
}

extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
                                              android::native_bridge_namespace_t* /* to */,
                                              const char* /* shared_libs_soname */) {
  return true;
}

extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
                                               int /* flag */,
                                               android::native_bridge_namespace_t* /* ns */) {
  return nullptr;
}


android::NativeBridgeCallbacks NativeBridgeItf{
    // v1
    .version = 3,
@@ -113,8 +118,7 @@ android::NativeBridgeCallbacks NativeBridgeItf {
    .unloadLibrary = &native_bridge3_unloadLibrary,
    .getError = &native_bridge3_getError,
    .isPathSupported = &native_bridge3_isPathSupported,
  .initNamespace = &native_bridge3_initNamespace,
    .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
    .createNamespace = &native_bridge3_createNamespace,
  .loadLibraryExt = &native_bridge3_loadLibraryExt
};
    .linkNamespaces = &native_bridge3_linkNamespaces,
    .loadLibraryExt = &native_bridge3_loadLibraryExt};
+12 −12
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ namespace android {

constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";

TEST_F(NativeBridgeTest, V3_InitNamespace) {
TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
  // Init
  ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
  ASSERT_TRUE(NativeBridgeAvailable());
@@ -30,7 +30,7 @@ TEST_F(NativeBridgeTest, V3_InitNamespace) {
  ASSERT_TRUE(NativeBridgeAvailable());

  ASSERT_EQ(3U, NativeBridgeGetVersion());
    ASSERT_EQ(true, NativeBridgeInitNamespace(nullptr, nullptr));
  ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));

  // Clean-up code_cache
  ASSERT_EQ(0, rmdir(kCodeCache));
Loading