按下电源键到启动Home应用过程详解(三)

2019-07-13 22:23发布

一: 这篇将分析手机从加电那一刻到Home应用启动的过程,如下图简要描述了启动过程
启动过程 system_server在开启核心服务的时候,其中有一个服务是ActivityManagerService,简称AMS; 主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,在系统进程到ready阶段的时候,AMS将会通过zygote启动Home应用 二:关于1号进程和0好进程进程
init进程是Android用户空间的1号进程,在linux中也存在0号进程;
当内核被加载到内存后,首先就会有完成内核初始化的函数start_kernel()从无到有的创建一个内核线程swap,并设置其PID为0,即进程0;它也叫闲逛进程;进程0执行的是cpu_idle()函数,该函数仅有一条hlt汇编指令,就是在系统闲置时用来降低电力的使用和减少热的产生。同时进程0的PCB叫做init_task,在很多链表中起了表头的作用。 init进程从不终止,用来创建和监控操作系统外层的所有进程的活动。
三:关于init进程
3.1 源码位置
system/core/init目录,其入口函数为system/core/init/init.c的main函数中 3.1 inti.c中main函数主要作用
- 创建基本文件系统目录并挂在文件系统
- 初始化内核Log系统
- 解析并触发inti.c配置文件中的各种action,service和command
- 属性服务的处理 3.2 init.c中main函数中相关方法的解释 mkdir(“/dev”, 0755)
创建文件目录命令,第一个为文件创建位置,第二个参数表示文件组操作权限
Linux 系统中采用三位十进制数表示权限,如0755, 0644.
0755->即用户具有读/写/执行权限,组用户和其它用户具有读写权限;
0644->即用户具有读写权限,组用户和其它用户具有只读权限; mount(“devpts”,“/dev/pts”,”devpts”,0,NULL)
linux 的理念就是everything is file
挂载是指将一个设备(通常是存储设备)挂接到一个已存在的目录上。 我们要访问存储设备中的文件,必须将文件所在的分区挂载到一个已存在的目录上, 然后通过访问这个目录来访问存储设备。
mount用法 四:关于init.rc的简要分析 4.1 该配置文件由Android初始化语言定义;
该配置文件由不同的Section组成,每一个Section都有不同的Action(行动)或者Service(服务),我们可以用On来声明一个Action;用service来声明一个Service;每一个Action或者Service都有若干Command(命令),每一个Command都有若干Trigger(触发条件); 这里的Service都是init进程的子进程,由关键字service,服务名和服务对应的命令的路径,命令的参数和Option(可选项,主要作为服务启动的配置参数)组成,代表在初始化阶段启动的程序 4.2 关于Android初始化语言中的Option中重要参数解读
-critical 核心服务,在一定时间内退出多次,将导致系统重启到revovery mode
-disable 开机时禁止此服务,但可以手动启动它 4.3 关于如何查看Command是在哪里执行
  • 在init_parser.c中,定义了一个keyword_info的宏,在这个文件中有很多KEYWORD的函数,执行Command就是执行这些函数
On early-init write / ..... start / ..... on定义了一个Action,write和start则是对应的Command,对应执行的函数为do_write和do_start 五:关于在init进程中启动的Service 5.1 在init.c的main函数中,执行到action_for_each_trigger(“boot”….),在触发boot Action的过程中,将要启动的Service与Command关联起来 5.2 init把Service作为一个进程,用Command通过fork的方式启动的,这样所有Service就是init的子进程了;由init启动的Service主要有ueventd,servicemanager,zygote,install,bootanim等,我们称这些Service为守护进程服务 5.3 这里的Service与Android开发中的service组件是否为同一个概念
不是,这里的Service是服务的概念,不同于Android开发过程的service组件;这里的Service多由C++实现; 5.4 属性服务的启动,即内置Action的启动 5.4.1 什么是属性服务
Linux系统启动的时候,由init初始化并开启属性服务;提供了一个系统属性共享内存区,用于存储全局系统设置信息。 属性服务的文件多是prop的文件格式;
Android的属性系统是一种特殊的Action,这种Action以”on property:”为前缀;
 在android 系统中,为统一管理系统的属性,设计了一个统一的属性系统。每个属性都有一个名称和值,他们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性。在编译的过程中会将各种系统参数汇总到build.proc 以及default.proc 这两个文件中,主要属性集中在build.proc中。系统在开机后将读取配置信息并构建共享缓冲区,加快查询速度。另外一个方面,SettingsProvider会在系统第一次初始化时(刷机第一次启动)后,将从Defaults.xml中读取数据然后写入数据库Settings.db 目录。并构建一个缓冲系统供其他应用查询。
属性服务详解
5.4.2 关于属性系统中创建的Socket
这个socket主要用于客户端和服务端的通信,便于操作属性系统的key-value;
- 这里的服务端我们可以将其抽象理解为在inti.c中的start_property_service函数,在这个函数中,创建一个服务端的socket,类似于servicesocket,并在0666端口进行监听;
- 这里的客户端主要在system/core/libcutils/properties.c的property_ set的函数中,在一系列处理之后,会创建客户端的Socket,并连接服务端; 六: Home应用是如何启动的
- zygote中通过fork系统调用创建system_server进程
- system_server进程创建各种服务,如ActivityManagerService,PackageManagerService
- 系统服务启动后会注册到ServiceManager中,用于Binder通信;
- ActivityManagerService进入systemReady状态 6.1 关于Zygote
他是一个守护进程服务,所有其他的Dalvik虚拟机进程都是通过zygote fork出来的,这样便可以共享虚拟机内存和框架层资源; 6.2 关于Zygote的配置
在linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。 在系统启动脚本init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
service zygote /system/bin/app_process
上述脚本表示要启动一个进程,名称为zygote, 可执行文件为/system/bin/app_process, –Xzygote /system/bin –zygote –start-system-server这些是传给zygote的参数; app_process对应的源码在frameworks/base/cmds/app_process目录下,其入口函数main在文件app_main.cpp中 6.3 关于zygote启动位置的一些疑问
- 既然zygote是在init.rc中定义的守护进程,那为什么不在init中直接启动,而是在app_process中完成加载?
- 这是因为zygote不同于其他的守护进程,他是由Java语言实现,不能通过init进程的fork方式启动,因此需要在app_process完成加载工作; 6.4 关于app_main.cpp的main方法的解释 int main(int argc, char* const argv[]) { if (!LOG_NDEBUG) { String8 argv_String; for (int i = 0; i < argc; ++i) { argv_String.append("""); argv_String.append(argv[i]); argv_String.append("" "); } ALOGV("app_process main with argv: %s", argv_String.string()); } AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); ... if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied. "); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); } } 这段函数主要作用是:
  • 调用AppRuntime类的start方法
6.5 查看AppRuntime类的start方法
AppRuntime的实现代码在app_main.cpp中 /* * Start the Android runtime. This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". * * Passes the main function two arguments, the class name and the specified * options string. */ void AndroidRuntime::start(const char* className, const Vector& options, bool zygote) { ALOGD(">>>>>> START %s uid %d <<<<<< ", className != NULL ? className : "(unknown)", getuid()); static const String8 startSystemServer("start-system-server"); /* * 'startSystemServer == true' means runtime is obsolete and not run from * init.rc anymore, so we print out the boot start event here. */ for (size_t i = 0; i < options.size(); ++i) { if (options[i] == startSystemServer) { /* 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); } //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s' ", kernelHack); /* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } //查看onVmCreated方法体可以看出这是一个空方法体,采用多态形式实际上调用的是AppRuntime的onVmCreated方法 onVmCreated(env); 该方法主要做了如下工作
- 创建Dalvik虚拟机 startVm(&mJavaVM, &env, zygote)
- 注册JNI方法 startReg(env) 6.6 startVm(&mJavaVM, &env, zygote)
- 通过属性系统获取虚拟机配置信息,设置虚拟机参数
- 调用JNI_CreateJavaVM创建虚拟机
我们可以通过dalvik/docs/dexopt/html查看虚拟机详细信息;或者通过adb shell dalvikvm查看 6.7 startReg(env)
- 正如之前说的日志系统,Java层可以不用加载so变实现native方法调用,其实正是这里采用的注册方法关联了Native方法和JNI实现方法
- startReg方法主要调用register_jni_procs方法。register_jni_procs方法传入RegJNIRec类型,通过查看类型的定义 static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), 使用REG_JNI宏,将函数名传给RegJNIRec, 这些函数最终都调用了RegisterMethodsOrDie方法完成JNI注册;关于RegisterMethodsOrDie方法,在前面的文章中已经有了讲解
Android运行时注册的共享库为libandroid_runtime.so; 在虚拟机创建的过程中已经完成加载,其他虚拟机是通过zygote fork的方式创建,则会共享libandroid_runtime.so 6.8 CallStaticVoidMethod(startClass, startMeth, strArray);
- 在AppRuntime类的start方法中最终会调用CallStaticVoidMethod方法,该方法是个JNI函数,其调用的是ZygoteInit的main方法;此时Java的代码正式出现;
- CallStaticVoidMethod的声明在jni.h中,但是你却找不到他的实现;其实CallStaticVoidMethod的方法是使用宏来定义的;同样的在jni.h中,我们可以看见 #define CALL_STATIC_TYPE_METHODA(_jtype, _jname) __NDK_FPABI__ _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID, jvalue* args) { return functions->CallStatic##_jname##MethodA(this, clazz, methodID, args); } 这里我们就不做过多研究,只要知道最终调用的是调用的是ZygoteInit的main方法即可 6.9 ZygoteInit.java的main方法 public static void main(String argv[]) { //为zygote进程创建一个Server socket ZygoteServer zygoteServer = new ZygoteServer(); // Mark zygote start. This ensures that thread creation will throw // an error. ZygoteHooks.startZygoteNoThreadCreation(); // Zygote goes into its own process group. try { /*setpgid(int pid, int pgid) 函数作用:将pid进程的进程组ID设置成pgid,创建一个新进程组或加入一个已存在的进程组*/ Os.setpgid(0, 0); } catch (ErrnoException ex) { throw new RuntimeException("Failed to setpgid(0,0)", ex); } try { Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit"); RuntimeInit.enableDdms(); // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } //Registers a server socket for zygote command connections zygoteServer.registerServerSocket(socketName); Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); /* preload方法主要做 1:加载/system/etc/preloaded-classes文件制定的class,preloaded-classes文件内容主要由WritePreloadedClassFile.java生成 2:加载框架层的资源文件,以便进程共享;这里加载了com.android.internal.R.array.preloaded_drawables 和 com.android.internal.R.array.preloaded_color_state_lists 这两个资源定义在frameworksasecore es esvaluesArrays.xml中; Arrays.xml里面定义的资源最终会被生成到framework-res.apk中,这样其他进程就可以共享资源了,使用方法为:android:background="@android:drawable/ic_menu_help" */ preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC"); gcAndFinalize(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false); // Zygote process unmounts root storage spaces. Zygote.nativeUnmountStorageOnInit(); // Set seccomp policy Seccomp.setPolicy(); ZygoteHooks.stopZygoteNoThreadCreation(); if (startSystemServer) { /** * Prepare the arguments and fork for the system server process. * zygote通过folk方式创建system_server进程,其方法为Zygote.forkSystemServer;forkSystemServer方法系统会检查system server进程是否启动成功,如果启动失败,则导致zygote重启;system server负责构建Native System Service和Java System Service,如果启动失败,整个java 世界也无从谈起 */ startSystemServer(abiList, socketName, zygoteServer); } Log.i(TAG, "Accepting command socket connections"); zygoteServer.runSelectLoop(abiList); zygoteServer.closeServerSocket(); } catch (Zygote.MethodAndArgsCaller caller) { caller.run(); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); zygoteServer.closeServerSocket(); throw ex; } } 我们看下registerServerSocket的实现 /** * Registers a server socket for zygote command connections * * @throws RuntimeException when open fails */ void registerServerSocket(String socketName) { if (mServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException(fullSocketName + " unset or invalid", ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); mServerSocket = new LocalServerSocket(fd); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } } 在这里使用了LocalServerSocket.java,如上调用LicalServerSocket.java的构造函数 /** * Create a LocalServerSocket from a file descriptor that's already * been created and bound. listen() will be called immediately on it. * Used for cases where file descriptors are passed in via environment * variables * * @param fd bound file descriptor * @throws IOException */ public LocalServerSocket(FileDescriptor fd) throws IOException { impl = new LocalSocketImpl(fd); impl.listen(LISTEN_BACKLOG); localAddress = impl.getSockAddress(); } 至此,我们已经为zygot创建了一个类型为LocalServerSocket的socket
  • 参考zygoteinit.java main方法里面的注释,我们简单对该方法做个整理 6.9.1 new ZygoteServer对象,ZygoteServer类主要作用是新建zygote进程的server socket 6.9.2 调用ZygoteServer对象的registerServerSocket的方法,生成LocalServerSocket类型的server socket,其应该为unix上的socket,并监听50端口 6.9.3 调用preload方法,该方法将
    -调用preloadClasses方法,预加载/system/etc/preloaded-classes文件里面的类
    -调用preloadResources方法,预加载com.android.internal.R.array.preloaded_drawables和com.android.internal.R.array.preloaded_color_state_lists资源文件,这两个资源定义在frameworksasecore es esvaluesArrays.xml中;
    Arrays.xml里面定义的资源最终会被生成到framework-res.apk中,这样其他进程就可以共享资源了,使用方法为:android:background=”@android:drawable/ic_menu_help” 6.9.4 调用startSystemServer方法,该方法调用过程如下 1) 通过fork的方式开启system_server进程,forkSystemServer方法系统会检查system server进程是否启动成功,如果启动失败,则导致zygote重启;system server负责构建Native System Service和Java System Service,如果启动失败,整个java 世界也无从谈起
pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); 2)调用handleSystemServerProcess方法,该方法主要调用ZygoteInit.zygoteInit方法 public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws Zygote.MethodAndArgsCaller { if (RuntimeInit.DEBUG) { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); } Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); //重定向log系统 RuntimeInit.redirectLogStreams(); //一些初始化设置 RuntimeInit.commonInit(); //nativeZygoteInit为native方法,其在AndroidRuntime.cpp总,有具体实现;最终调用到AppRuntime的onZygoteInit方法,该方法开启了system_server的binder通信通道 ZygoteInit.nativeZygoteInit(); //applicationInit将调用invokeStaticMain方法,invokeStaticMain方法将采用反射的方式获取frameworksaseservicesjavacomandroidserver、SystemServer.java,然后得到main方法,注意此处并没有调用main方法;并抛出MethodAndArgsCaller异常;该异常在zygoteinit.java的main函数中有捕获,当main方法捕获到该异常之后,调用该异常的run方法,传入的参数是SystemServer.java的main方法,此时才是真正执行main方法的地方;这样做的好处是跳出调用栈,直接返回到zygoteinit的main方法中 RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); } 7.0 SystemServer.java main方法详解 /** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); } public SystemServer() { // Check for factory test mode. mFactoryTestMode = FactoryTest.getMode(); // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed")); } private void run() { try { ...... // Prepare the main looper thread (this thread). Looper.prepareMainLooper(); // Initialize native services.加载android_servers库 System.loadLibrary("android_servers"); // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context.创建system的context createSystemContext(); // Create the system service manager.创建SystemServiceManager,SystemServer进程主要是用来构建系统各种service服务的,而SystemServiceManager就是这些服务的管理对象。 mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart); //将SystemServiceManager对象保存SystemServer进程中的一个数据结构中。 LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); } finally { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } // Start services. try { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices"); startBootstrapServices();// 主要用于启动系统Boot级服务 startCoreServices();//主要用于启动系统核心的服务 startOtherServices();//主要用于启动一些非紧要或者是非需要及时启动的服务 } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } finally { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } ...... // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } 我们主要分析一下该run方法,在该方法中会涉及到启动Home App 1)设置系统时间,时区
2)设置系统属性
3)加载android_servers.so
4 ) 调用createSystemContex方法,创建sytem的context;
activityThread.getSystemContext()返回的是ContextImpl对象,ContextImpl继承自Context private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); mSystemContext.setTheme(DEFAULT_SYSTEM_THEME); } 5)创建SystemServiceManager对象,(SystemServer进程主要是用来构建系统各种service服务的,而SystemServiceManager就是这些服务的管理对象;)创建完对象之后调用LocalServices.addService添加到LocalServices.java的一个ArrayMap中 6) 调用startBootstrapServices开启boot级service
在启动service之前先介绍下SystemServiceManager对象的startService方法
该方法传入class类型,通过反射的方式拿到传入类的实例,拿到对应类实例之后,将其添加到ArrayList类型的mServices中进行生命周期管理,并同时调用该实例的onStart方法 // Services that should receive lifecycle events. private final ArrayList mServices = new ArrayList(); 现在来看下 startBootstrapServices方法的执行流程
a: 通过 SystemServiceManager.startService(Installer.class)创建Install的systemservice,Install是系统安装apk时的一个服务类;
b: 通过 SystemServiceManager.startService方法开启ActivityManagerService,并为其设置SysServiceManager和Installer mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); c: 开启PowerManagerService 该类用来管理电源
d: 开启LightsService,该类用来管理LED和背光
e: 开启DisplayManagerService,显示管理服务DisplayManagerService,支持多种显示类型的多个显示器的镜像显示,包括内建的显示类型(本地)、HDMI显示类型以及支持WIFI Display 协议( MIRACAST),实现本地设备在远程显示器上的镜像显示。
f: 开启UserManagerService
g: 开启PackageManagerService,这个不是通过startservice启动,而是通过如下启动 mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); 7)调用startCoreServices启动系统核心的服务 private void startCoreServices() { // Tracks the battery level. Requires LightService. mSystemServiceManager.startService(BatteryService.class); // Tracks application usage stats. mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); // Tracks whether the updatable WebView is in a ready state and watches for update installs. mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class); } a. 调用startservice开启BatteryService
b. 调用startservice开启UsageStatsService
c. 调用startservice开启WebViewUpdateService 8)调用startOtherServices() 主要用于启动一些非紧要或者是非需要及时启动的服务 8.0 如何显示Home App的
在上面的讲解中,我们调用了startOtherServices方法,该方法将调用mActivityManagerService.systemReady方法,告诉系统已经好了,可以显示Home App了 // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. mActivityManagerService.systemReady(new Runnable() { @Override public void run() { Slog.i(TAG, "Making services ready"); ...... try { startSystemUi(context); } catch (Throwable e) { reportWtf("starting System UI", e); } ...... } }); systemReady方法将调用startHomeActivityLocked启动Home App startHomeActivityLocked(currentUserId, "systemReady"); boolean startHomeActivityLocked(int userId, String reason) { if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) { // We are running in factory test mode, but unable to find // the factory test app, so just sit around displaying the // error message and don't try to start anything. return false; } Intent intent = getHomeIntent(); ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null) { intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); // Don't do this if the home app is currently being // instrumented. aInfo = new ActivityInfo(aInfo); aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId); ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true); if (app == null || app.instrumentationClass == null) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); mActivityStarter.startHomeActivityLocked(intent, aInfo, reason); } } else { Slog.wtf(TAG, "No home screen found for " + intent, new Throwable()); } return true; } 由于launcher是一个apk,在之前的packagemanagerserver已经对其进行解析,因此可以获得对应的intent信息,接着调用ActivityStarter.java startHomeActivityLocked方法,该方法调用startActivityLocked方法 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) { mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason); //activity的启动方式 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/, null /*container*/, null /*inTask*/); if (mSupervisor.inResumeTopActivity) { // If we are in resume section already, home activity will be initialized, but not // resumed (to avoid recursive resume) and will stay that way until something pokes it // again. We need to schedule another resume. mSupervisor.scheduleResumeTopActivities(); } } 在startActivityLocked有一个重要的方法如下 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, 该方法主要作用是在启动activity的时候,PMS会去找清单文件,是否有注册的Activity; 该方法实际上调用的是PackageManagerService(PMS)的resolveIntent方法, @Override public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { ... final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId); return bestChoice; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } chooseBestActivity方法会根据priority优先级来判断来选择最好的一个activity,这个priority会在launcher 的manifest.xml中进行配置;当查询到这个activity之后,Launcher App就被启动起来,接着完成activity的启动过程,即进行activity相应生命周期的流程,展示UI; 在ActivityStarter.java中的startActivityLocked方法中,会调用startActivityUnchecked方法
这个方法处理了Activity的启动模式,比如是否需要新建一个任务栈,栈里面是否需要复用已经存在的Activity实例等等。而且启动模式还要配合flag,比如说NEW_TASK等。并且在清单文件里面的启动模式的配置要优先于flags
在startActivityUnchecked方法体内部有如下关键代码 ActivityStack.logStartActivity( EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task); mTargetStack.mLastPausedActivity = null; sendPowerHintForLaunchStartIfNeeded(false /* forceSend */); mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions); ActivityStack是activity的栈的管理类;调用ActivityStack类的startActivityLocked之后;