ANDROID has been around for about 5 months now, and its Java package has been very uncomfortable. This time I downloaded the source code of Froyo and prepared to analyze the running process of Android. I always wondered — could I replace the JAVA layer? Android is the most difficult to remember the location of its several files, here will give a detailed path, convenient for other visitors to understand.

There’s no fixed order, but it’s probably something that starts with startup. My thinking is that the more I know about Android, the more likely I am to make the best, most refined changes to it. Really didn’t like the Java layer.

 

User space init

I’m not going to analyze the first program that Linux starts, init.

Init code is in /system/core/init/init.c. If you are interested, start with the main function

All other important Android processes are forked by init loading the init.rc configuration file. Among them, the most important init. Rc is located in the source/system/core/rootdir.

Init. rc has its own syntax, but Google will find out.

 

The birth of zygote ii

 

The zygote program is created by app_process, which starts with a line in init.rc.

service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-server

// The first zygote is the name of the service, the actual program is in system/bin app_process, followed by the program’s startup parameter Socket zygote Stream 666

// init will create a Unix domain socket. 666 is RWX read/write execution permission. onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media

The app_process in the/frameworks/base/CMDS/app_process/app_main CPP.

Let’s analyze its mian function.

int main(int argc, const char* const argv[]) { //argc = 5 //argv=["/system/bin/app_process" "-Xzygote" "/system/bin" "--zygote" "--start-system-server"] // These are global variables in ProcessState.cpp mArgC = argc; // mArgV = argv; // mArgLen = 0; for (int i=0; i<argc; i++) { mArgLen += strlen(argv[i]) + 1; } mArgLen--; AppRuntime runtime; // define AppRuntime const char *arg; const char *argv0; argv0 = argv[0]; //argv0="/system/bin/app_process" // Process command line arguments // ignore argv[0] argc--; argv++; // Everything up to '--' or first non '-' arg goes to the vm int i = runtime.addVmArguments(argc, argv); Next arg is parent directory if (I < argc) {runtime.mParentDir = argv[I ++]; // Set the parent directory to /system/bin} // // Next arg is startup classname or "--zygote" if (I < argc) {arg = argv[I ++]; if (0 == strcmp("--zygote", arg)) { bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false; // Normal case is true setArgv0(argv0, "zygote"); set_process_name("zygote"); runtime.start("com.android.internal.os.ZygoteInit", startSystemServer); // Start Java zygoteInit} else {set_process_name(argv0); runtime.mClassName = arg; // Remainder of args get passed to startup class main() runtime.mArgC = argc-i; runtime.mArgV = argv+i; LOGV("App process is starting with pid=%d, class=%s./n", getpid(), runtime.getClassName()); runtime.start(); } } else { LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); fprintf(stderr, "Error: no class name or --zygote supplied./n"); app_usage(); return 10; }}Copy the code

As you can see from the code comments above, much of the work is handed over to the Runtime object, which is also defined in this CPP file. Let’s see.

Class AppRuntime: public AndroidRuntime // The base class is AndroidRuntime. mParentDir(NULL) , mClassName(NULL) , mArgC(0) , mArgV(NULL) { } #if 0 // this appears to be unused const char* getParentDir() const { return mParentDir; } #endif const char* getClassName() const { return mClassName; } virtual void onStarted() {sp<ProcessState> proc = ProcessState::self(); if (proc->supportsProcesses()) { LOGV("App process: starting thread pool./n"); proc->startThreadPool(); } app_init(mClassName, mArgC, mArgV); if (ProcessState::self()->supportsProcesses()) { IPCThreadState::self()->stopProcess(); } } virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); if (proc->supportsProcesses()) { LOGV("App process: starting thread pool./n"); proc->startThreadPool(); } } virtual void onExit(int code) { if (mClassName == NULL) { // if zygote if (ProcessState::self()->supportsProcesses()) { IPCThreadState::self()->stopProcess(); } } AndroidRuntime::onExit(code); } const char* mParentDir; const char* mClassName; int mArgC; const char* const* mArgV; }; }Copy the code

Among them, the base class AndroidRuntime. H in frameworks/base/include/android_runtime/AndroidRuntime. H is defined. Let’s take a look at some of the definitions.

Namespace Android {// This class is a class that interacts with the Java virtual machine. Class AndroidRuntime {public: AndroidRuntime(); virtual ~AndroidRuntime(); /** * Register a set of methods in the specified class. */ static int registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods); /** * Call a static Java function that takes no arguments and returns void. */ status_t callStatic(const char* className, const char* methodName); /** * Call a class's static main method with the given arguments, */ status_t callMain(const char* className, int argc, const char* const argv[]); /** * Find a class, with the input either of the form * "package/class" or "package.class". */ static jclass findClass(JNIEnv* env, const char* className); int addVmArguments(int argc, const char* const argv[]); void start(const char *classname, const bool startSystemServer); void start(); // start in android.util.RuntimeInit static AndroidRuntime* getRuntime(); /** * This gets called after the JavaVM has initialized. Override it * with the system's native entry point. */ virtual void onStarted() = 0; /** * This gets called after the JavaVM has initialized after a Zygote * fork. Override it to initialize threads, etc. Upon return, the * correct static main will be invoked. */ virtual void onZygoteInit() {}; /** * Called when the Java application exits. The default * implementation calls exit(code). */ virtual void onExit(int code); /** create a new thread that is visible from Java */ static void createJavaThread(const char* name, void (*start)(void *), void* arg); /** return a pointer to the VM running in this process */ static JavaVM* getJavaVM() { return mJavaVM; } /** return a pointer to the JNIEnv pointer for this thread */ static JNIEnv* getJNIEnv(); private: static int startReg(JNIEnv* env); int startVm(JavaVM** pJavaVM, JNIEnv** pEnv); Vector<JavaVMOption> mOptions; /* JNI JavaVM pointer */ static JavaVM* mJavaVM; /* * Thread creation helpers. */ static int javaCreateThreadEtc( android_thread_func_t entryFunction, void* userData, const char* threadName, int32_t threadPriority, size_t threadStackSize, android_thread_id_t* threadId); static int javaThreadShell(void* args); }; // Returns the Unix file descriptor for a ParcelFileDescriptor object extern int getParcelFileDescriptorFD(JNIEnv* env, jobject object); }Copy the code

AndroidRuntime classes work primarily with Java and seem to only work when called by the Framework. My own JNI libraries generally don’t use the convenience functions defined in AndroidRuntime, although they are static. Here’s why (you have to look at its implementation file to see why)

AndroidRuntime::mJavaVM = NULL; // System-wide, the first constructor call is in app_process. ! AndroidRuntime::AndroidRuntime() { SkGraphics::Init(); // this sets our preference for 16bit images during decode // in case the src is opaque and 24bit SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config); // This cache is shared between browser native images, and java "purgeable" // bitmaps. This globalpool is for images that do not either use the java // heap, or are not backed by ashmem. See BitmapFactory.cpp for the key // java call site. SkImageRef_GlobalPool::SetRAMBudget(512 * 1024); // There is also a global font cache, but its budget is specified in code // see SkFontHost_android.cpp // Pre-allocate enough space to hold a fair number of options. mOptions.setCapacity(20); assert(gCurRuntime == NULL); // one per process gCurRuntime = this; } // The onXXX function is called from here, Static void com_android_internal_os_RuntimeInit_finishInit(JNIEnv* env, jobject clazz) { gCurRuntime->onStarted(); } static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); } static jint com_android_internal_os_RuntimeInit_isComputerOn(JNIEnv* env, jobject clazz) { return 1; } static void com_android_internal_os_RuntimeInit_turnComputerOn(JNIEnv* env, jobject clazz) { } static jint com_android_internal_os_RuntimeInit_getQwertyKeyboard(JNIEnv* env, jobject clazz) { char* value = getenv("qwerty"); if (value ! = NULL && strcmp(value, "true") == 0) { return 1; } return 0; } / / omit some int AndroidRuntime: : addVmArguments (int arg c, const char * const argv []) {int I; for (i = 0; i<argc; i++) { if (argv[i][0] ! = '-') { return i; } if (argv[i][1] == '-' && argv[i][2] == 0) { return i+1; } // If the vm is not up, save the options JavaVMOption opt; memset(&opt, 0, sizeof(opt)); opt.optionString = (char*)argv[i]; mOptions.add(opt); } return i; }Copy the code

The location of the CPP in/frameworks/base/core/jni/AndroidRuntime CPP.

Go back to the main app_process, here have been shipped to the runtime. The start (” com. Android. Internal. OS. ZygoteInit “, startSystemServer) this sentence comes, should go in to see what is dry start.

Instead, look at code analysis.