android启动--深入理解启动HOME
ok, 通过前面讲解,系统已经从 init 进程 --> 启动 zygote --> 启动 SystemServer --> ??? 那么现在应该启动什么呢?
从前面分析来看,基本的native及 java 世界的环境都已建立完成,那么还差一个HOME主页显示? 可视化系统下面即将开始了。
在讲解 Zygote 中,有一个函数:
main @ frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
这里利用 runSelectLoopMode() 函数处理客户连接及客户请求
private static void runSelectLoopMode(){
while (true) {
// 利用select进行多路I/O 监听
index = selectReadable(fdArray);
// 如果有客户端连接则accept并加入到ArrayList中
if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
}else {
// 否则交给ZygoteConnection的 runOnce()函数
done = peers.get(index).runOnce();
}
}
...
}
-->
上面在客户端连接使用 ZygoteConnection 类,具体 runOnce()功能如下:
runOnce @ frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
args = readArgumentList();
// 根据客户端给定的参数,利用 forkAndSpecialize 创建进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid,
parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags, rlimits);
// 根据pid值进行处理子进程及父进程
if (pid == 0) {
// in child
handleChildProc(parsedArgs, descriptors, newStderr);
// should never happen
return true;
} else { /* pid != 0 */
// in parent...pid of < 0 means failure
return handleParentProc(pid, descriptors, parsedArgs);
}
...
}
总结:客户端利用Zygote代表 ZygoteConnection 类请求 zygote 创建新的进程,创建成功后并分别对子进程及父进程单独流程处理。
应用安装完毕后,还需要有一个HOME应用来负责将它们在桌面上显示出来,默认就是Launcher2应用程序,这里将介绍一下 Launcher2 启动过程, 主要分为6个大过程来启动:
在 SystemServer.java 中对于 ActivityManagerService 的处理简单说明下:
1、ActivityManagerService.main(factoryTest);
通过AThread线程对象来内部创建了一个ActivityManagerService实例,然后将这个实例保存其成员变量mService中,接着又把这个ActivityManagerService实例保存在ActivityManagerService类的静态成员变量mSelf中 :
ActivityManagerService m = new ActivityManagerService();
mService = m;
mSelf = mService;
2、ActivityManagerService.setSystemProcess();
系统中的应用程序的所有信息都保存在PackageManagerService,所需要的应用信息从这里提取即可。
ApplicationInfo info =
mSelf.mContext.getPackageManager().getApplicationInfo(
"android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info);
3、在run() 函数后半段,有很多的 xxx.systemReady();这里是通知各个服务,系统已经准备就绪。
其中如下代码片段:
// 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.
((ActivityManagerService)ActivityManagerNative.getDefault())
.systemReady()
-->
systemReady @ frameworks\base\services\java\com\android\server\am\ActivityManagerSe
rvice.java
public void systemReady(final Runnable goingCallback){
...
resumeTopActivityLocked(null); // 这里启动Home应用程序
...
}
-->
private final boolean resumeTopActivityLocked(HistoryRecord prev){
// Find the first activity that is not finishing.
HistoryRecord next = topRunningActivityLocked(null);
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
return startHomeActivityLocked();
}
...
}
利用topRunningActivityLocked 返回的是当前系统Activity堆栈最顶端的Activity 而为 null 则调用 topRunningActivityLocked()
4、启动HOME应用程序
private boolean startHomeActivityLocked() {
...
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
ActivityInfo aInfo =
intent.resolveActivityInfo(mContext.getPackageManager(),STOCK_PM_FLAGS);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,aInfo.applicationInfo.uid);
if (app == null || app.instrumentationClass == null) {
startActivityLocked(null, intent, null, null, 0, aInfo,
null, null, 0, 0, 0, false, false);
}
}
这里会创建一个 CATEGORY_HOME 类型的 Intent ,通过resolveActivityInfo函数向 PackageManagerService 查询 CATEGORY 是否类型为 HOME 类型应用。这里返回 com.android.launcher2.Launcher 这个 Activity。第一次启动则利用startActivityLocked启动这个Activity。
查看 packages\apps\Launcher2\AndroidManifest.xml 内容:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
</intent-filter>
5、下面就启动 com.android.launcher2.Launcher 这个 Activity
首先从执行 onCreate 函数开始简单过一下代码调用大致关系:
onCreate --> mModel.startLoader(this, true); -->
调用到 LauncherModel.java
public void startLoader(Context context, boolean isLaunching)
这里并非直接加载应用程序,而是利用发消息由LoaderThread处理
mLoaderThread = new LoaderThread(context, oldThread, isLaunching);
mLoaderThread.start();
-->
public void run() {
补充:移动开发 , Android ,