深入浅出 - Android系统移植与平台开发(九)- Android系统system_server及Home启动
来源:互联网 发布:360 手机网络收藏夹 编辑:程序博客网 时间:2024/05/22 13:25
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所示:
图 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,它是ZygoteSocket客户端的参数封装类
// 在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进程根据客户端数据请求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启动
- 深入浅出 - Android系统移植与平台开发(九)- Android系统system_server及Home启动
- 深入浅出 - Android系统移植与平台开发(七)- Android系统的启动
- 深入浅出 - Android系统移植与平台开发(七)- Android系统的启动
- 深入浅出 - Android系统移植与平台开发
- 深入浅出 - Android系统移植与平台开发
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 深入浅出 - Android系统移植与平台开发(四)- Android启动流程
- 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速
- JX8NET团队正式启用项目管理软件 DotProject
- windows7登陆smb用户名不存在
- oj(一)w
- HQL语句总结
- hibernate连接池参数说明
- 深入浅出 - Android系统移植与平台开发(九)- Android系统system_server及Home启动
- 求连续向量的最大子和问题(扫描算法)
- 黑马程序员——集合二
- oj(一)x
- mount 用法详解
- HDU 1251 统计难题 (Trie树)
- JAVA中HashMap详解
- 我的第一个C#程序-智能拼图图示
- oj(一)y