3.3 Zygote守护进程与system_server进程

Android的执行环境和Java执行环境有着本质的差别,在Android系统中每一个应用程序都是一独立的进程,当一个进程死掉时,不会影响其他进程的执行,这能极大的保证Android系统的稳定。 Zygote守护进程的启动是Android执行环境启动的開始阶段, Zygote进程通过Linux系统特有的Fork机制分裂克隆出全然相同的执行环境,全部的Android应用程序都是Zygote进程的子进程,system_server进程作为Zygote进程的嫡长子进程,对Android系统服务又有着重要意义。本节内容是我们研究Android系统启动的開始,让我们从Zygote守护进程的启动開始分析吧。

3.3.1 Zygote守护进程的启动

在init.rc中,通过init进程启动了Zygote服务:

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

socket zygote stream 666

……

通过上面init.rc的代码可知。Zygote服务相应程序为/system/bin/app_process。服务名为zygote,參数列表为:-Xzygote/system/bin --zygote --start-system-server。

在启动zygote 服务时,在/dev/socket/文件夹下建立一个streamsocket文件:zygote。权限为666。

我们能够通过以下的命令来查找Zygote进程的源代码:

find ./ -nameAndroid.mk  -exec grep -l app_process {}\;

注:find命令用于查找一个文件,-exec  xxx {} \;表示:在前面命令的结果里执行grep 命令。

由上述命令结果可知,Zygote进程代码为frameworks/base/cmds/app_process/app_main.cpp

找到该程序的main入口函数:

118 int main(int argc,const char* const argv[])

119 {

120     // These are global variables inProcessState.cpp

121     mArgC = argc;

122     mArgV = argv;

123

124     mArgLen = 0;

125     for (int i=0; i<argc; i++) {

126         mArgLen += strlen(argv[i]) + 1;

127     }

128     mArgLen--;

129

130     AppRuntimeruntime;

131     const char *arg;

132     const char *argv0;

133

134     argv0 = argv[0];

135

136     // Process command line arguments

137     // ignore argv[0]

138     argc--;

139     argv++;

141     // Everything up to '--' or first non '-'arg goes to the vm

142     // 在zygote服务的參数列表中:/system/bin–zygote--start-system-server

// 以“--”和非“-”开头的參数,是dalvik的參数,交给Vm来处理

143     int i = runtime.addVmArguments(argc, argv);

144

145     // 找到zygote的文件夹:/system/bin

146     if (i < argc) {

147         runtime.mParentDir = argv[i++];

148     }

149

150     // 假设接下来的參数是:--zygote --start-system-server的话,

// 设置argv0=“zygote”,startSystemServer= true,启动java VM

151     if (i < argc) {

152         arg = argv[i++];

153         if (0 == strcmp("--zygote",arg)) {

154             bool startSystemServer = (i <argc) ?

155                     strcmp(argv[i],"--start-system-server") == 0 : false;

156             setArgv0(argv0,"zygote");

157             set_process_name("zygote");

158             runtime.start("com.android.internal.os.ZygoteInit",

159                 startSystemServer);

160         } else {

161             set_process_name(argv0);

162

163             runtime.mClassName = arg;

164

165             // Remainder of args get passed tostartup class main()

166             runtime.mArgC = argc-i;

167             runtime.mArgV = argv+i;

168

169             LOGV("App process is startingwith pid=%d, class=%s.\n",

170                  getpid(), runtime.getClassName());

171             runtime.start();

172         }

173     } else {

174         LOG_ALWAYS_FATAL("app_process: noclass name or --zygote supplied.");

175         fprintf(stderr, "Error: no classname or --zygote supplied.\n");

176         app_usage();

177         return 10;

178     }

179

180 }

依据service zygote的參数,启动Android执行时环境:

runtime.start("com.android.internal.os.ZygoteInit",startSystemServer),依据前面的分析可知:startSystemServer= true,runtime是AppRuntime的对象。AppRuntime是AndroidRuntime的子类,如图xx-xx所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbXJfcmFwdG9y/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

图 xx-xx AndroidRuntime与AppRuntime类关系图

由上面类图可知,runtime.start方法在AndroidRuntime里实现:

@frameworks/base/core/jni/AndroidRuntime.cpp

883 void AndroidRuntime::start(const char*className, const bool startSystemServer)

884{

// logcat里最显眼的字样

885    LOGD("\n>>>>>> AndroidRuntime START %s<<<<<<\n",

886            className != NULL ? className : "(unknown)");

887

888    char* slashClassName = NULL;

889    char* cp;

890    JNIEnv* env;

891

// 启动Dalvik虚拟机。在AndroidRuntime::startVm方法中。设置了大量VM的启动參数。

// 最后通过JNI调用JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs)函数启动虚拟机

918    /* start the virtual machine */

919    if (startVm(&mJavaVM, &env) != 0)

920        goto bail;

921

922    /*

923     * Register android functions.   //注冊系统使用的JNI函数

924     */

925    if (startReg(env) < 0) {

926        LOGE("Unable to register all android natives\n");

927        goto bail;

928    }

930    /*

931     * We want to call main() with a String array with arguments in it.

932     * At present we only have one argument, the class name.  Create an

933     * array to hold it.

934     */

935    jclass stringClass;

936    jobjectArray strArray;

937    jstring classNameStr;

938    jstring startSystemServerStr;

939

// 从虚拟机执行环境里,查找到String类

940    stringClass = env->FindClass("java/lang/String");

941    assert(stringClass != NULL);

// 创建一个String数组,有两个元素(strArray =  new String[2])

942    strArray = env->NewObjectArray(2, stringClass, NULL);

943    assert(strArray != NULL);

// 创建一个Java String对象,初始值为:className的值,

// 即:“com.android.internal.os.ZygoteInit”

944    classNameStr = env->NewStringUTF(className);

945    assert(classNameStr != NULL);

// 设置strArray 第一个元素的值为:classNameStr(strArray[0] = classNameStr)

946    env->SetObjectArrayElement(strArray, 0, classNameStr);

// 创建一个Java String对象,初始值为:startSystemServer的值,即:“true”

947    startSystemServerStr = env->NewStringUTF(startSystemServer ?

948                                                 "true" : "false");

// 设置strArray 第二个元素的值为:strArray[1]=startSystemServerStr

949    env->SetObjectArrayElement(strArray, 1, startSystemServerStr);

// 依据上面的解释。我们能够用以下的Java代码来表示:

// String[] strArray = new strArray[2];

// strArray[0]  ="com.android.internal.os.ZygoteInit"

// strArray[1]  = "true"

950

951    /*

952     * Start VM.  This thread becomesthe main thread of the VM, and will

953     * not return until the VM exits.

954     */

955    jclass startClass;

956    jmethodID startMeth;

957

958    slashClassName = strdup(className);

959    for (cp = slashClassName; *cp != '\0'; cp++)

960        if (*cp == '.')

961            *cp = '/';

// 将com.android.internal.os.ZygoteInit中的包分隔符“.”换成“/”

// 即:slashClassName ="com/android/internal/os/ZygoteInit"

962

963    startClass = env->FindClass(slashClassName);

// 从VM中查找ZygoteInit类。难道它要在VM里执行这个它?

964    if (startClass == NULL) {

965        LOGE("JavaVM unable to locate class '%s'\n", slashClassName);

966        /* keep going */

967    } else {

968        startMeth = env->GetStaticMethodID(startClass, "main",

969            "([Ljava/lang/String;)V");

// 从ZygoteInit类中查找名字为main的静态方法。

// 而且main方法有一个參数String[]。返回值为void。

// 这不就是Java应用程序的main函数的签名吗?难道要调用它??

970        if (startMeth == NULL) {

971            LOGE("JavaVM unable to find main() in '%s'\n", className);

972            /* keep going */

973        } else {

974            env->CallStaticVoidMethod(startClass, startMeth, strArray);

// 果然,调用了ZygoteInit类里的main方法。

这不就是在VM里执行ZygoteInit程序吗。!

980        }

981    }

... 省略部分代码...

991 }

由上面的分析简单总结下:

从源代码的角度在AndroidRuntime::start方法实现了以下功能:

1>通过startVm来启动Dalvik虚拟机(简称DVM),而且注冊了一些本地JNI函数,因为这个时候DVM里还没有程序,仅仅是个空的DVM执行环境

2>通过AndroidRuntime::start的參数,在JNI代码里执行第一个Java程序ZygoteInit,将其作为DVM的主线程,同一时候给它传递两个在JNI中构建的參数:

"com/android/internal/os/ZygoteInit"和"true"

我们再从进程的角度来分析下:

Zygote进程由init进程作为Service启动。在Zygote进程里通过startVm启动了VM执行环境(如图xx-xx中①所看到的),通过JNI代码在VM环境中执行ZygoteInit.java。作为VM中的主线程。

图 xx-xx Zygote进程与Dalvik虚拟机

3.3.2 ZygoteInit类的功能与system_server进程的创建

Zygote将DVM执行环境准备好了。而且開始调用执行ZygoteInit.java代码。

以下我们分析下ZygoteInit.java代码。

@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

554     public static void main(String argv[]) {

555         try {

... 省略部分代码...

561             registerZygoteSocket();  // 注冊ZygoteSocket。创建一个Socket的服务端

... 省略部分代码...

564             preloadClasses();            // 预载入类

565             //cacheRegisterMaps();

566             preloadResources();       // 预资源类

... 省略部分代码...

// 假设ZygoteInit的第二个參数为"true"。则调用startSystemServer()

581             if(argv[1].equals("true")) {

582                 startSystemServer();

583             } else if(!argv[1].equals("false")) {

584                 throw newRuntimeException(argv[0] + USAGE_STRING);

585             }

... 省略部分代码...

603     }

依据main函数的第二个參数。调用了startSystemServer:

508     private static boolean startSystemServer()

511         String args[] = {

512             "--setuid=1000",

513             "--setgid=1000",

514"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",

515            "--capabilities=130104352,130104352",

516             "--runtime-init",

517             "--nice-name=system_server",

518            "com.android.server.SystemServer",

519         };

520         ZygoteConnection.Arguments parsedArgs= null;

521

522         int pid;

523

524         try {

// 创建ZygoteConnection的内部类Arguments,它是ZygoteSocketclient的參数封装类

// 在Arguments的构造方法里对args[]进行了解析,以下Zygote.forkSystemServer会用到。

525             parsedArgs = newZygoteConnection.Arguments(args);

... 省略部分代码...

536             /* Request to fork the system server process*/

537             pid = Zygote.forkSystemServer(

538                     parsedArgs.uid,parsedArgs.gid,

539                     parsedArgs.gids,debugFlags, null,

540                     parsedArgs.permittedCapabilities,

541                    parsedArgs.effectiveCapabilities);

// 调用Zygote的静态方法forkSystemServer()。用来创建了一个

// 名字为system_server的进程。该方法是一个本地方法

// 在libcore/dalvik/src/main/java/dalvik/system/Zygote.java里定义。

// 本地实如今dalvik/vm/native/dalvik_system_Zygote.c中

542         } catch (IllegalArgumentException ex){

543             throw new RuntimeException(ex);

544         }

545

546         /* For child process */

547         if (pid == 0) {

548            handleSystemServerProcess(parsedArgs);

549         }

550

551         return true;

552     }

通过Zygote.forkSystemServer方法克隆了一个新的进程system_server。除了进程ID号pid它和Zygote进程的代码和数据全然一样,关于克隆具体内容,请查看fork系统调用相关知识。

在新创建的子进程system_server中调用handleSystemServerProcess:

491     private static voidhandleSystemServerProcess(

492             ZygoteConnection.ArgumentsparsedArgs)

493             throwsZygoteInit.MethodAndArgsCaller {

494

// 在新创建的子进程里将ZygoteSocket关闭

495         closeServerSocket();

... 省略部分代码...

// 将"--nice-name=system_server,com.android.server.SystemServer"传递给RuntimeInit.zygoteInit()

// 在RuntimeInit.zygoteInit方法里,调用了SystemServer的main方法,即在新进程里执行SystemServer.java

501        RuntimeInit.zygoteInit(parsedArgs.remainingArgs);

502         /* should never reach here */

503     }

至此。Zygote的第一个嫡长子进程system_server创建完成,而且開始执行其main方法,我们做下总结,如图xx-xx所看到的。

图 xx-xx  system_server进程的创建

①:在Zygote进程通过startVm启动Dalvik虚拟机(简称DVM)。在DVM里通过JNI调用ZygoteInit.main(),启动DVM里第一个主线程。

②:在ZygoteInit.java中绑定了ZygoteSocket并预载入类和资源。

③:通过Zygote.forkSystemServer()本地方法。在Linux中分裂fork出Zygote的第一个子进程。取名为system_server,该进程中的代码和数据与父进程Zygote全然一样。

④:在Zygote进程中通过RuntimeInit.zygoteInit(),调用SystemServer.main()。从而在system_server中执行SystemServer.java代码。

在Zygote进程创建时,init.rc脚本中创建了/dev/socket/zygote文件,它在ZygoteInit中被绑定为服务器端,用来接收克隆Zygote进程的请求,它相应用程序的创建有着重要的意义,其创建步骤例如以下图所看到的:

图 xx-xx  应用程序的创建

①  Zygote进程绑定并通过select监听ZygoteSocket(/dev/socket/zygote)

②  其他进程发出socket连接请求,用于创建新应用程序

③  Zygote和请求发起者建立新连接用于通信。接收待创建应用程序信息

④:Zygote进程依据client数据请求Fork出新的子进程

在ZygoteInit中预载入类和预加资源对Android整个执行环境有着至关重要的意义,预载入的类是指大量的Android框架层代码。这些类有数千个,当Android应用程序执行时都要载入这些类,相同的预载入资源是指一些系统的图片、图标、字符串资源。

假设这些类和资源推迟到Android应用程序启动时。那么应用程序的启动速度会大大减少,会直接影响用户体验,Android充分利用了Linux中fork进程时会克隆父进程数据和代码的特点。将类和资源提前载入到父进程里,从而大大提高了启动速度。

3.3.3 system_server进程的执行

@frameworks/base/services/java/com/android/server/SystemServer.java

596    native public static void init1(String[] args);   // init1方法为本地方法

598    public static void main(String[] args) {

... 省略部分代码...

// 载入本地库android_servers,添头加尾后本地库文件名称为:libandroid_servers.so

624        System.loadLibrary("android_servers");

625        init1(args);

626     }

在system_server进程里载入了libandroid_servers.so本地库。依据JNI机制,当Java代码中通过System.load载入一个本地动态库时,会自己主动调用该动态库中的JNI_Onload方法。通常在JNI_Onload方法中注冊本地函数与Java方法映射关系:

@frameworks/base/services/jni/onload.cpp

20 extern "C" jint JNI_OnLoad(JavaVM*vm, void* reserved)

21 {

22     JNIEnv* env = NULL;

23     jint result = -1;

24

25     if (vm->GetEnv((void**) &env,JNI_VERSION_1_4) != JNI_OK) {

26         LOGE("GetEnv failed!");

27         return result;

28     }

29     LOG_ASSERT(env, "Could not retrievethe env!");

30

31    register_android_server_PowerManagerService(env);

32     register_android_server_InputManager(env);

33    register_android_server_LightsService(env);

34    register_android_server_AlarmManagerService(env);

35    register_android_server_BatteryService(env);

36     register_android_server_UsbService(env);

37    register_android_server_VibratorService(env);

38     register_android_server_SystemServer(env);// 它实如今com_android_server_SystemServer.cpp中

39    register_android_server_location_GpsLocationProvider(env);

40

41     return JNI_VERSION_1_4;

42 }

@frameworks/base/services/jni/com_android_server_SystemServer.cpp

22namespace android {

23

24 extern"C" int system_init();

25

26 staticvoid android_server_SystemServer_init1(JNIEnv* env, jobject clazz)

27 {

28     system_init();// 被SystemServer.java调用。在frameworks/base/cmds/system_server/library/system_init.cpp中实现

// system_init.cpp被编译成libsystem_server.so库。被libandroid_servers.so引用

29 }

30

31 /*

32  * JNI registration.

33  */

// 由此可见。SystemServer.java中调用的init1方法,映射到了android_server_SystemServer_init1方法

34 staticJNINativeMethod gMethods[] = {

35     /* name, signature, funcPtr */

36     { "init1","([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1},

37 };

38  // 该方法被frameworks/base/services/jni/onload.cpp回调,用来注冊本地方法与Java方法的映射

39 intregister_android_server_SystemServer(JNIEnv* env)

40 {

41     return jniRegisterNativeMethods(env,"com/android/server/SystemServer",

42             gMethods, NELEM(gMethods));

43 }

44

45 }; //namespace android

在register_android_server_SystemServer方法中注冊本地方法与Java方法,通过映射关系可知,Java层的init1方法调用了本地的system_init方法:

@frameworks/base/cmds/system_server/library/system_init.cpp

54 extern"C" status_t system_init()

55 {

56     LOGI("Entered system_init()");

... 省略部分代码...

66     char propBuf[PROPERTY_VALUE_MAX];

67    property_get("system_init.startsurfaceflinger", propBuf,"1");

68     if (strcmp(propBuf, "1") == 0) {

69         // Start the SurfaceFlinger

70         SurfaceFlinger::instantiate(); //  启动SurfaceFlinger本地系统服务

71     }

72

73     // Start the sensor service

74     SensorService::instantiate();        // 启动SensorService本地系统服务

... 省略部分代码...

99    LOGI("System server: starting Android runtime.\n");

100

101    AndroidRuntime* runtime = AndroidRuntime::getRuntime();

102

103    LOGI("System server: starting Android services.\n");

104    runtime->callStatic("com/android/server/SystemServer","init2");  // 调用Java环境中SystemServer.java的init2方法

... 省略部分代码...

115    return NO_ERROR;

116 }

在system_init方法里开启了几个本地系统服务:SurfaceFlinger和SensorService,然后从本地又调回了Java执行环境中的SystemServer.java中的init2方法。之所以这么做,原因是上层Android系统服务的执行要依赖于本地系统服务的执行。所以system_server先保障本地服务的执行,然后再回执行Android系统服务。

SystemServer.java中的init2方法执行:

628    public static final void init2() {

629        Slog.i(TAG, "Entered the Android system server!");

630        Thread thr = new ServerThread();

631        thr.setName("android.server.ServerThread");

632        thr.start();

633     }

在init2中创建并开启了一个线程ServerThread,在线程的Run方法中

59 class ServerThread extends Thread {

... 省略部分代码...

80    @Override

81    public void run() {

// 开启主线程消息队列

85        Looper.prepare();

... 省略部分代码...

131        // Critical services...

132        try {

//加入Android系统服务

133            Slog.i(TAG, "Entropy Service");

134            ServiceManager.addService("entropy", new EntropyService());

//加入Android系统服务

136            Slog.i(TAG, "Power Manager");

137            power = new PowerManagerService();

138            ServiceManager.addService(Context.POWER_SERVICE, power);

//加入Android系统服务

140            Slog.i(TAG, "Activity Manager");

141            context = ActivityManagerService.main(factoryTest);

//加入Android系统服务

143            Slog.i(TAG, "TelephonyRegistry");

144            ServiceManager.addService("telephony.registry", newTelephonyRegistry(context));

145

... 省略部分代码。加入了大量Android系统服务...

473        // It is now time to start up the app processes...

474

475        if (devicePolicy != null) {

476            devicePolicy.systemReady();

477        }

478

479        if (notification != null) {

480            notification.systemReady();

481        }

482

483        if (statusBar != null) {

484            statusBar.systemReady();

485        }

486        wm.systemReady();

487        power.systemReady();

488        try {

489            pm.systemReady();

490        } catch (RemoteException e) {

491        }

... 省略部分代码...

507        // We now tell the activitymanager it is okay to run third party

508        // code.  It will call back intous once it has gotten to the state

509        // where third party code can really run (but before it has actually

510        // started launching the initial applications), for us to complete our

511        // initialization.

512        ((ActivityManagerService)ActivityManagerNative.getDefault())

513                 .systemReady(new Runnable(){     // 调用ActivityManagerService的systemReady。通知系统准备就绪。

...省略部分代码...

});

542        Looper.loop();   // system_service主线程队列開始循环等待消息

543        Slog.d(TAG, "System ServerThread is exiting!");

544     }

545 }

由前面分析可知,system_server进程的主要作用就是启动并执行Android系统服务,这些服务执行在system_server进程中,由此可见其重要性。

图x-x system_server进程

Android系统中服务分为两种:本地服务和Android系统服务,我们将Android2.3系统中这些服务分别罗列出来。以供參考。

Ø 本地服务主要包括:

服务名

作用

SurfaceFlinger

显示层混合器

SensorService

传感器服务

AudioFlinger

音频管理

MediaPlayerService

多媒体播放器服务

CameraService

摄像头服务

AudioPolicyService

音频策略管理服务

Ø Android系统服务:

服务名

作用

EntropyService

提供熵服务。用于产生随机数

PowerManagerService

电源管理服务

ActivityManagerService

管理Activity画面

TelephonyRegistry

注冊电话模块的事件响应

PackageManagerService

程序包管理服务

AccountManagerService

联系人账户管理服务

ContentService

ContentProvider服务。提供跨进程数据共享

BatteryService

电池管理服务

LightsService

自然光强度感应传感器服务

VibratorService

震动器服务

AlarmManagerService

定时器管理服务

WindowManagerService

窗体管理服务

BluetoothService

蓝牙服务

DevicePolicyManagerService

提供一些系统级别的设置及属性

StatusBarManagerService

状态栏管理服务

ClipboardService

系统剪切板服务

InputMethodManagerService

输入法管理服务

NetStatService

网络状态服务

NetworkManagementService

网络管理服务

ConnectivityService

网络连接管理服务

ThrottleService

节流阀控制服务

AccessibilityManagerService

辅助管理程序截获全部的用户输入。并依据这些输入给用户一些额外的反馈,起到辅助的效果,View的点击、焦点等事件分发管理服务

MountService

磁盘载入服务

NotificationManagerService

通知管理服务,通常和StatusBarManagerService

DeviceStorageMonitorService

存储设备容量监听服务

LocationManagerService

位置管理服务

SearchManagerService

搜索管理服务

DropBoxManagerService

系统日志文件管理服务

WallpaperManagerService

壁纸管理服务

AudioService

AudioFlinger上层的封装的音量控制管理服务

UsbService

USB Host和device管理服务

UiModeManagerService

UI模式管理服务,监听车载、座机等场合下UI的变化

BackupManagerService

备份服务

AppWidgetService

应用桌面部件服务

RecognitionManagerService

身份识别服务

DiskStatsService

磁盘统计服务

3.3.4Home桌面的启动

当Android系统服务启动完成后。system_service进程会通知Android系统服务系统启动完成,在ActivityManagerService.systemReady方法里会启动Android系统桌面应用程序:launcher。

@frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

386     public ActivityStack mMainStack;

... 省略部分代码...

6089    public void systemReady(final Runnable goingCallback) {

... 省略部分代码...

6254        synchronized (this) {

... 省略部分代码...

6288            mMainStack.resumeTopActivityLocked(null);   //  在Activity栈中显示栈顶的Activity画面

6289        }

6290     }

在ActivityManagerService中维护了一个ActivityStack,它用来管理Activity的执行状态,在栈顶的Activity即是正在执行的画面,当ActivityManagerService准备就绪后。显示ActivityStack中栈顶画面。

@frameworks/base/services/java/com/android/server/am/ActivityStack.java

125    final ActivityManagerService mService;

...省略部分代码...

1051    final boolean resumeTopActivityLocked(ActivityRecord prev) {

1052        // Find the first activity that is not finishing.

// 返回ActivityStack栈顶的Activity,因为刚启动Android系统,所以返回null

1053        ActivityRecord next = topRunningActivityLocked(null);

...省略部分代码...

1060        if (next == null) {

1061            // There are no more activities! Let's just start up the

1062            // Launcher...

1063            if (mMainStack) {

1064                 return mService.startHomeActivityLocked();  // 假设Activity栈顶没有Activity,则启动Launcher。即:HOME

1065            }

1066        }

因为Android系统刚启动,ActivityStack栈中还没有不论什么执行的Activity,所以这时要启动HOME应用程序作为主画面,从而显示桌面应用程序。

在Android中,启动一个Activity有两种方式:显示Intent启动和隐式Intent启动。

显示Intent启动:在Intent对象中指定Intent对象的接收者。是点对点的启动方式。

隐式Intent启动:相似于广播机制。在发送的Intent中通过Action和Category来匹配接收者,因此在Android系统中同意发出的Intent对象启动多个Activity,这样的方式保证了Android中全部应用程序的公平性。

Android的HOME应用程序的启动是通过隐式Intent启动的,我们能够查看HOME应用程序的AndroidManifest.xml文件来确定它的Intent对象的匹配内容:

@packages/apps/Launcher2/AndroidManifest.xml

1<?xml version="1.0" encoding="utf-8"?>

... 省略部分代码...

20 <manifest

21    xmlns:android="http://schemas.android.com/apk/res/android"

22     package="com.android.launcher"

23    android:sharedUserId="@string/sharedUserId"

24     >

65    <application

66        android:name="com.android.launcher2.LauncherApplication"

67        android:process="@string/process"

68        android:label="@string/application_name"

69        android:icon="@drawable/ic_launcher_home">

70

71         <activity

72            android:name="com.android.launcher2.Launcher"

73            android:launchMode="singleTask"

74            android:clearTaskOnLaunch="true"

75            android:stateNotNeeded="true"

76             android:theme="@style/Theme"

77            android:screenOrientation="nosensor"

78            android:windowSoftInputMode="stateUnspecified|adjustPan">

 79            <intent-filter>

 80                 <actionandroid:name="android.intent.action.MAIN" />

 81                 <categoryandroid:name="android.intent.category.HOME" />

 82                 <categoryandroid:name="android.intent.category.DEFAULT" />

 83                 <categoryandroid:name="android.intent.category.MONKEY"/>

 84            </intent-filter>

85         </activity>

在Android系统启动的终于阶段通过Intent对象启动HOME应用程序,该Intent中封装了两个基本的属性:action=”android.intent.action.MAIN”。category=“android.intent.category.HOME”。通过上面的代码能够看出来,launcher2应用程序的intent-filter匹配项里包括了HOME应用程序启动的“必要条件”。

深入浅出 - Android系统移植与平台开发(九)- Android系统system_server及Home启动的更多相关文章

  1. 深入浅出 - Android系统移植与平台开发(一)

    深入浅出 - Android系统移植与平台开发(一) 分类: Android移植2012-09-05 14:16 16173人阅读 评论(12) 收藏 举报 androidgitgooglejdkub ...

  2. 深入浅出-Android系统移植与平台开发(一)- Android4.0系统的下载与编译

    作者:唐老师,华清远见嵌入式学院讲师. 一.Android4.0系统的下载与编译 Android系统的下载与编译,Google的官方网站上已经给出了详细的说明,请参照Android的官方网址: htt ...

  3. 深入浅出 - Android系统移植与平台开发(三)- 编译并运行Android4.0模拟器

    作者:唐老师,华清远见嵌入式学院讲师. 1.   编译Android模拟器 在Ubuntu下,我们可以在源码里编译出自己的模拟器及SDK等编译工具,当然这个和在windows里下载的看起来没有什么区别 ...

  4. 深入浅出 - Android系统移植与平台开发(五)- 编译Android源码(转)

    2.3编译Android源码 Android源码体积非常庞大,由Dalvik虚拟机.Linux内核.编译系统.框架代码.Android定制C库.测试套件.系统应用程序等部分组成,在编译Android源 ...

  5. 深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)

    第四章.Android编译系统与定制Android平台系统 4.1Android编译系统 Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同 ...

  6. 深入浅出 - Android系统移植与平台开发(十一)- Android系统的定制(瘋耔修改篇一)

    首先非常感谢原文作者为我们提供的知识库,因为有你们的贡献,我们的开发难度更显简单 原文 :   http://blog.csdn.net/mr_raptor/article/details/30113 ...

  7. 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速

    作者:唐老师,华清远见嵌入式学院讲师. Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新 版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们 ...

  8. 深入浅出 - Android系统移植与平台开发(七)- 初识HAL

    作者:唐老师,华清远见嵌入式学院讲师. 1. HAL的module与stub HAL(Hardware AbstractLayer)硬件抽象层是Google开发的Android系统里上层应用对底层硬件 ...

  9. 深入浅出 - Android系统移植与平台开发(七)- 初识HAL【转】

    本文转载自:http://blog.csdn.net/mr_raptor/article/details/8069588 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   ...

随机推荐

  1. numpy.clip(a, a_min, a_max, out=None)(values < a_min are replaced with a_min, and those > a_max with a_max.)

    numpy.clip(a, a_min, a_max, out=None) Clip (limit) the values in an array. Given an interval, values ...

  2. 【Luogu】P1410子序列(DP)

    题目链接 我DP是真的菜啊啊啊啊啊! f[i][j]表示考虑前i个数,有i-j+1个数组成一个上升子序列,且不以i结尾的尾端最小值. 设a为j个数组成的序列,且以i结尾:b为i-j+1个数组成的序列, ...

  3. BZOJ1925 [Sdoi2010]地精部落 【dp】

    题目 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi,其中Hi是1到N ...

  4. VS链接错误: LNIK1123

    问题:编译一个VS工程程序,出现连接错误:"LNK1123: 转换到 COFF 期间失败: 文件无效或损坏" 原因分析:连接器LNK是通过调用cvtres.exe完成文件向coff ...

  5. P1282 多米诺骨牌 (差值DP+背包)

    题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+1+1+1=9, ...

  6. 【前端学习笔记】ajax与php之间的互动

    ajax通常会牵扯到跨域问题,所以我们通常的解决方案是,通过ajax将参数传到后台php文件中 在后台通过php文件进行跨域访问api,再将结果返回到ajax响应中.需要注意一下几点: 1.可以通过& ...

  7. 解决 IDEA 中src下xml等资源文件无法读取的问题

    该问题的实质是,idea对classpath的规定. 在eclipse中,把资源文件放在src文件夹下,是可以找到的: 但是在idea中,直接把资源文件放在src文件夹下,如果不进行设置,是不能被找到 ...

  8. 【索引】理解MySQL——索引与优化

    MySQL 索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索 ...

  9. perl学习之精髓中的精髓

    1.是函数就有返回值: 比如:chomp函数,其可以除去换行符,但其也有返回值 chomp($xx) #这是去除xx的换行符 $yy=chomp($xx)  #这是看这次除去了几个换行符,也就是函数运 ...

  10. python实现显示安装进度条

    一直很好奇那种安装进度条,或者启动程序时候显示的进度条是怎么实现的,学习了python之后,sys模块中有个方法可以实现,代码如下:   1 2 3 4 5 6     import sys,time ...