intmain(int argc, char* const argv[]) { AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++;
if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } elseif (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); } }
/* * Start the Android runtime. This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". * * Passes the main function two arguments, the class name and the specified * options string. */ void AndroidRuntime::start(constchar* className, const Vector<String8>& options, bool zygote) { ALOGD(">>>>>> START %s uid %d <<<<<<\n", className != NULL ? className : "(unknown)", getuid());
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { // ... // Look for a native bridge. // // The intended flow here is, in the case of a running system: // // Runtime::Init() (zygote): // LoadNativeBridge -> dlopen from cmd line parameter. // | // V // Runtime::Start() (zygote): // No-op wrt native bridge. // | // | start app // V // DidForkFromZygote(action) // action = kUnload -> dlclose native bridge. // action = kInitialize -> initialize library // // // The intended flow here is, in the case of a simple dalvikvm call: // // Runtime::Init(): // LoadNativeBridge -> dlopen from cmd line parameter. // | // V // Runtime::Start(): // DidForkFromZygote(kInitialize) -> try to initialize any native bridge given. // No-op wrt native bridge. { std::string native_bridge_file_name = runtime_options.ReleaseOrDefault(Opt::NativeBridge); is_native_bridge_loaded_ = LoadNativeBridge(native_bridge_file_name); } // ... }
boolLoadNativeBridge(constchar* nb_library_filename, const NativeBridgeRuntimeCallbacks* runtime_cbs){ // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not // multi-threaded, so we do not need locking here.
if (nb_library_filename == nullptr || *nb_library_filename == 0) { CloseNativeBridge(false); returnfalse; } else { if (!NativeBridgeNameAcceptable(nb_library_filename)) { CloseNativeBridge(true); } else { // Try to open the library. void* handle = dlopen(nb_library_filename, RTLD_LAZY); if (handle != nullptr) { callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, kNativeBridgeInterfaceSymbol)); if (callbacks != nullptr) { if (isCompatibleWith(NAMESPACE_VERSION)) { // Store the handle for later. native_bridge_handle = handle; } else { callbacks = nullptr; dlclose(handle); ALOGW("Unsupported native bridge interface."); } } else { dlclose(handle); } }
// Two failure conditions: could not find library (dlopen failed), or could not find native // bridge interface (dlsym failed). Both are an error and close the native bridge. if (callbacks == nullptr) { CloseNativeBridge(true); } else { runtime_callbacks = runtime_cbs; state = NativeBridgeState::kOpened; } } return state == NativeBridgeState::kOpened; } }
/* * Start the Dalvik Virtual Machine. * * Various arguments, most determined by system properties, are passed in. * The "mOptions" vector is updated. * * CAUTION: when adding options in here, be careful not to put the * char buffer inside a nested scope. Adding the buffer to the * options using mOptions.add() does not copy the buffer, so if the * buffer goes out of scope the option may be overwritten. It's best * to put the buffer at the top of the function so that it is more * unlikely that someone will surround it in a scope at a later time * and thus introduce a bug. * * Returns 0 on success. */ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote) { JavaVMInitArgs initArgs; // ...
// Native bridge library. "0" means that native bridge is disabled. // // Note: bridging is only enabled for the zygote. Other runs of // app_process may not have the permissions to mount etc. property_get("ro.dalvik.vm.native.bridge", propBuf, ""); if (propBuf[0] == '\0') { ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty"); } elseif (zygote && strcmp(propBuf, "0") != 0) { snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX, "-XX:NativeBridge=%s", propBuf); addOption(nativeBridgeLibrary); } // ... initArgs.version = JNI_VERSION_1_4; initArgs.options = mOptions.editArray(); initArgs.nOptions = mOptions.size(); initArgs.ignoreUnrecognized = JNI_FALSE;
/* * Initialize the VM. * * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread. * If this call succeeds, the VM is ready, and we can start issuing * JNI calls. */ if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); return-1; }
// Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized // later. staticconst NativeBridgeCallbacks* callbacks = nullptr;
// The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks. staticconstexprconstchar* kNativeBridgeInterfaceSymbol = "NativeBridgeItf";
boolLoadNativeBridge(constchar* nb_library_filename, const NativeBridgeRuntimeCallbacks* runtime_cbs){ // Try to open the library. void* handle = dlopen(nb_library_filename, RTLD_LAZY); if (handle != nullptr) { callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, kNativeBridgeInterfaceSymbol)); if (callbacks != nullptr) { if (isCompatibleWith(NAMESPACE_VERSION)) { // Store the handle for later. native_bridge_handle = handle; } else { callbacks = nullptr; dlclose(handle); ALOGW("Unsupported native bridge interface."); } } else { dlclose(handle); } } return state == NativeBridgeState::kOpened; } }
void* handle = dlopen(nb_library_filename, RTLD_LAZY); if (handle != nullptr) { callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, kNativeBridgeInterfaceSymbol)); if (callbacks != nullptr) { if (isCompatibleWith(NAMESPACE_VERSION)) { // Store the handle for later. native_bridge_handle = handle; } else { callbacks = nullptr; dlclose(handle); ALOGW("Unsupported native bridge interface."); } } else { dlclose(handle); } }
如果isCompatibleWith这个函数返回false,那么就会close掉我们的so库。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// The policy of invoking Nativebridge changed in v3 with/without namespace. // Suggest Nativebridge implementation not maintain backward-compatible. staticboolisCompatibleWith(constuint32_t version){ // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported // version. if (callbacks == nullptr || callbacks->version == 0 || version == 0) { returnfalse; }
// If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check. if (callbacks->version >= SIGNAL_VERSION) { return callbacks->isCompatibleWith(version); }
void Runtime::InitNonZygoteOrPostFork( JNIEnv* env, bool is_system_server, // This is true when we are initializing a child-zygote. It requires // native bridge initialization to be able to run guest native code in // doPreload(). bool is_child_zygote, NativeBridgeAction action, constchar* isa, bool profile_system_server) { if (is_native_bridge_loaded_) { switch (action) { case NativeBridgeAction::kUnload: UnloadNativeBridge(); is_native_bridge_loaded_ = false; break; case NativeBridgeAction::kInitialize: InitializeNativeBridge(env, isa); break; } } // ... }