深入浅出 - Android系统移植与平台开发(九)- Android系统system_server及Home启动

81 篇文章 5 订阅

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应用程序启动的“必要条件”。









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值