編輯:關於Android編程
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system # zygote需要一個套接字 onrestart write /sys/android_power/request_state wake # zygote重啟的話,需要執行這個操作 onrestart write /sys/power/state on onrestart restart media onrestart restart netd*上述腳本表示要啟動一個進程,名稱為zygote, 可執行文件為/system/bin/app_process, --Xzygote /system/bin --zygote --start-system-server這些是傳給zygote的參數,其余部分的作用見注釋。
int main(int argc, char* const argv[]) { // These are global variables in ProcessState.cpp mArgC = argc; mArgV = argv; mArgLen = 0; for (int i=0; i三、main函數主要就是創建了runtime實例,並且解析參數,然後調用runtime的start函數,接著我們分析AppRuntime的start函數
// 首先明確下傳進來的參數 className == "com.android.internal.os.ZygoteInit" options == "start-system-server" void AndroidRuntime::start(const char* className, const char* options) { ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n", className != NULL ? className : "(unknown)"); /* * 'startSystemServer == true' means runtime is obsolete and not run from * init.rc anymore, so we print out the boot start event here. */ if (strcmp(options, "start-system-server") == 0) { /* track our progress through the boot sequence */ const int LOG_BOOT_PROGRESS_START = 3000; LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); } const char* rootDir = getenv("ANDROID_ROOT"); if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) { LOG_FATAL("No root directory specified, and /android does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); //配置ANDROID_ROOT環境變量 } //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); /* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env) != 0) { // 創建虛擬機 return; } onVmCreated(env); /* * Register android functions. */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } /* * We want to call main() with a String array with arguments in it. * At present we have two arguments, the class name and an option string. * Create an array to hold them. */ jclass stringClass; jobjectArray strArray; jstring classNameStr; jstring optionsStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(2, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); optionsStr = env->NewStringUTF(options); env->SetObjectArrayElement(strArray, 1, optionsStr); /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { /* 調用com.android.internal.os.ZygoteInit的main函數,strArray是參數,數組裡面有兩個元素, className == "com.android.internal.os.ZygoteInit" options == "start-system-server" */ env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } free(slashClassName); ALOGD("Shutting down VM\n"); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n"); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly\n"); }四、start函數主要做了以下幾件事情:
public static void main(String argv[]) { try { // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); registerZygoteSocket(); // 1、創建一個套接字,用於監聽ams發過來的fork請求 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(); // 2、加載classes 和resources, 後面會詳細分析 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup gc(); // If requested, start system server directly from Zygote if (argv.length != 2) { throw new RuntimeException(argv[0] + USAGE_STRING); } if (argv[1].equals("start-system-server")) { startSystemServer(); //3、 創建system server進程,ams wms pms等常見service都在該進程裡面 } else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); } Log.i(TAG, "Accepting command socket connections"); if (ZYGOTE_FORK_MODE) { runForkMode(); } else { runSelectLoopMode(); // 4、進入循環監聽模式,監聽外來請求 } closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }五、com.android.internal.os.ZygoteInit的main函數主要做了四件事情:
public class ZygoteInit { ... private static LocalServerSocket sServerSocket; private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote"; private static void registerZygoteSocket() { if(sServerSocket == NULL) { int fileDesc; String env = System.getenv(ANDROID_SOCKET_ENV); // 獲取環境變量 fileDesc = Integer.parseInt(env); sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc)); } } }*這裡通過System.getenv()獲取環境變量ANDROID_SOCKET_ENV的值,通過這個文件描述符表示/dev/socket/zygote。那麼這個環境變量又是誰設置的呢?執行系統啟動腳本init.rc的init.c文件裡面有個service_start()函數就是用來分析zygote並創建和設置相應socket的。
void service_start(struct service *svc, const char* dynamic_args) { ... pid = fork(); if ( pid == 0) { struct socketinfo *si; ... for (si = svc->sockets; si; si = si->next) { int socket_type = (!strcmp(si->type, "stream") ? SOCK_STREAM : (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET)); int s = create_socket(si->name, socket_type, si->perm, si->uid, si->gid); publish_socket(si->name, s); } } ... } #define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_" #define ANDROID_SOCKET_DIR "/dev/socket" static void publish_socket(const char *name, int fd) { char key[64] = ANDROID_SOCKET_ENV_PREFIX; char val[64]; strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) -1, name, sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX)); snprintf(val, sizeof(val), "%d", fd); add_environment(key, val); // ANDROID_SOCKET_zygote = val fcntl(fd, F_SETFD, 0); }*這裡每一個service命令都會使init進程調用fork函數創建一個新的進程來分析裡面的socket選項,然後調用create_socket()函數在/dev/socket目錄下創建一個設備文件,然後獲得一個文件描述符並通過publish_socket()寫入到環境變量中去。這樣就把zygote這個socket的文件描述符寫到ANDROID_SOCKET_zygote裡面去了,這裡創建socket文件描述符的create_socket()函數,最後通過調用execve(svc->args[0], (char**)arg_ptrs, (char**)ENV)去執行zygote的可執行程序,並將環境變量ENV參數傳遞過去了。所以ZygoteInit.registerZygoteSocket()函數就可以直接從環境變量中取出這個文件描述符來使用。如果其他進程需要打開這個/dev/socket/zygote 文件來和Zygote進程通信就需要通過文件名字連接LocalServerSocket。
private static boolean startSystemServer() { String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006...", "--capabilities=13010432,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); int pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities)); if (pid == 0) { // 子進程 handleSystemServerProcess(parsedArgs); } return true; // 父進程直接返回true }*這裡Zygote進程通過調用Zygote.forkSystemServer()函數創建一個新的進程來啟動SystemServer組件。
public class ZygoteInit { .... private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) { closeServerSocket(); // 子進程不需要zygote套接字,直接關閉 FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO); ... RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } } public class RuntimeInit { ... public static final void zygoteInit(int targetSdkVersion, String[] argv) { redirectLogStreams(); commonInit(); zygoteInitNative(); // 是一個native函數,主要完成Binder通信機制的初始化 applicationInit(targetSdkVersion, argv); } public static final native void zygoteInitNative(); private static void applicationInit(int targetSdkVersion, String[] argv) { VMRuntime.getRuntime().setTargetHeapUtilizatoin(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args; args = new Arguments(argv); invokeStaticMain(args.startClass, args.startArgs); } // 這個 className = "com.android.server.SystemServer" private static void invokeStaticMain(String className, String[] argv) { Class cl; cl = Class.forName(className); Method m; m = cl.getMethod("main", new Class[] {String[].class}); ... throw new ZygoteInit.MethodAndArgsCaller(m, argv); } }*這個RuntimeInit.ZygoteInit()函數主要執行兩個操作:一是調用zygoteInitNative來執行一個Binder進程間通信機制的初始化工作;二是調用com.android.server.SystemServer類的main函數。
static JNINativeMethod gMethods[] = { .... { "zygoteInitNative", "()V", (void*) com_android_internal_os_RuntimeInit_zygoteInit }, .... }; static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); // 就是啟動Binder通信 } virtual void onZygoteInit() { sp*SystemServer.main :proc = ProcessState::self(); // 每個進程一份ProcessState對象,打開Binder驅動 if(proc->supportsProcess()){ proc->startThreadPool(); // 啟動一個線程用於Binder通信 } }
public class SystemServer { native public static void init1(Strig[] args); public static void main(String[] args) { .... VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); System.loadLibrary("android_servers"); init1(args); } public static final void init2() { Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } }*@frameworks/base/services/jni/com_android_server_SystemServer.cpp
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz) { system_init(); } status_t system_init() { sp*這個SystemServer的main()函數首先會調用JNI方法init1,init1()會調用SystemServer的init2,在init2裡面創建一個ServerThread線程執行一些系統關鍵服務的啟動操作。proc(ProcessState::self()); sp sm = defaultServiceManager(); ... AndroidRuntime* runtime = AndroidRuntime::getRuntime(); JNIEnv* env = rungime->getJNIEnv(); jclass clazz = env->FindClass("com/android/server/SystemServer"); jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V"); env->CallStaticVoidMethod(clazz, methodId); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return NO_ERROR; }
class ServerThread extends Thread { ... public void run() { Looper.prepare(); // Critical services ... ServiceManager.addService(Context.POWER_SERVICE, new PoperManagerService()); ActivityManagerService.main(); PackageManagerService.main(context); ... } }*到現在為止,zygote已經fork()子進程完成了SystemServer組件的初始化啟動操作,回到zygote.main()裡面調用runSelectLoopMode()進入一個循環再前面創建的socket接口上等待ActivityManagerService請求創建新的應用程序。
3、runSelectLoopMode
public class ZygoteInit { .... private static void runSelectLoopMode() throws MethodAndArgsCaller { ArrayList*這裡while(true)循環裡面調用selectReadble(),這是一個native函數,類似select使用多路復用I/O模型。當返回0的時候表示有客戶端連接上,ZygoteConnection表示Zygote的一個客戶端,每當客戶端連接上的時候acceptCommandPeer()返回一個ZygoteConnection對象,ZygoteConnection裡面保存著accpet()返回的LocalSocket對象。然後將相應的文件描述符添加到fds裡面,下次再對其調用selelct輪詢。當返回值大於0的時候表示有客戶端發過來的數據請求,交給ZygoteConnection對象的runOnce()函數處理。fds = new ArrayList(); ArrayList peers = new ArrayList(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(NULL); int loopCount = GC_LOOP_COUNT; // 10 while(true) { fdArray = fds.toArray(fdArray); index = selectReadble(fdArray); // 類似Linux下的select輪詢,native 函數 if(index < 0) { ... } else if(index == 0) { // 表示有客戶端連接上 ZygoteConnection newPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else { // 客戶端發送了請求過來,交給ZygoteConnection的runOnce()函數完成 boolean done = peers.get(index).runOnce(); if(done) { peers.remove(index); fds.remove(index); } } } } private static ZygoteConnection acceptCommandPeer() { ... return new ZygoteConnection(sServerSocket.accept()); } }
static jint com_android_internal_os_ZygoteInit_selectReadable ( JNIEnv *env, jobject clazz, jobjectArray fds) { if (fds == NULL) { jniThrowNullPointerException(env, "fds == null"); return -1; } jsize length = env->GetArrayLength(fds); fd_set fdset; if (env->ExceptionOccurred() != NULL) { return -1; } FD_ZERO(&fdset); int nfds = 0; for (jsize i = 0; i < length; i++) { jobject fdObj = env->GetObjectArrayElement(fds, i); if (env->ExceptionOccurred() != NULL) { return -1; } if (fdObj == NULL) { continue; } int fd = jniGetFDFromFileDescriptor(env, fdObj); if (env->ExceptionOccurred() != NULL) { return -1; } FD_SET(fd, &fdset); if (fd >= nfds) { nfds = fd + 1; } } int err; do { err = select (nfds, &fdset, NULL, NULL, NULL); } while (err < 0 && errno == EINTR); if (err < 0) { jniThrowIOException(env, errno); return -1; } for (jsize i = 0; i < length; i++) { jobject fdObj = env->GetObjectArrayElement(fds, i); if (env->ExceptionOccurred() != NULL) { return -1; } if (fdObj == NULL) { continue; } int fd = jniGetFDFromFileDescriptor(env, fdObj); if (env->ExceptionOccurred() != NULL) { return -1; } if (FD_ISSET(fd, &fdset)) { return (jint)i; } } return -1; }總結:
*應用進程和服務進程位於不同的進程中,他們之間是通過IPC進行數據傳遞的。
本博文講解流程TouchEvent相關事件簡介流程圖分解講解總結與歸納一.TouchEvent相關事件簡介 android TouchEvent相關事件有&nb
RecyclerView 是 android-support-v7-21 版本中新增的一個 Widgets, 還有一個 CardView 會在下次介紹使用。官方介紹 Re
一、ExpandableListView介紹 一個垂直滾動的顯示兩個級別(Child,Group)列表項的視圖,列表項來自ExpandableListAdapter
其實webview加載資源的速度並不慢,但是如果資源多了,當然就很慢。圖片、css 、js 、html這些資源每個大概需要10-200ms ,一般都是30ms就ok了。不