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 内容:
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() {
waitForOtherThread();
...
if (loadWorkspaceFirst) {
if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
loadAndBindWorkspace();
} else {
if (DEBUG_LOADERS) Log.d(TAG, "step 1: special: loading all apps");
loadAndBindAllApps();
}
...
// second step
if (loadWorkspaceFirst) {
if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
loadAndBindAllApps();
} else {
if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
loadAndBindWorkspace();
}
...
}
这里调用 loadAndBindAllApps 进一下操作
private void loadAndBindAllApps() {
loadAllAppsByBatch();
}
private void loadAllAppsByBatch() {
// 先构造一个 CATEGORY_LAUNCHER 类型的 Intent
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// 利用 queryIntentActivities 所有类型为 Intent.ACTION_MAIN 及
// Intent.CATEGORY_LAUNCHER 的 Activity
final PackageManager packageManager = mContext.getPackageManager();
apps = packageManager.queryIntentActivities(mainIntent, 0);
// 保存于 mAllAppsList 应用列表中
for (int j=0; i
// This builds the icon bitmaps.
mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
i++;
}
// 通过 Callbacks
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
mHandler.post(...) {
callbacks.bindAllApplications(added);
}
}
-->
/**
* Add the icons for all apps.
*
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindAllApplications(ArrayList
mAllAppsGrid.setApps(apps);
}
6、AllApps2D.java 继续加载应用程序
public void setApps(ArrayList
mAllAppsList.clear();
addApps(list);
}
public void addApps(ArrayList
final int N = list.size();
for (int i=0; i
final ApplicationInfo item = list.get(i);
int index = Collections.binarySearch(mAllAppsList, item,
LauncherModel.APP_NAME_COMPARATOR);
if (index < 0) {
index = -(index+1);
}
mAllAppsList.add(index, item);
}
mAppsAdapter.notifyDataSetChanged();
}
这里创建了 ApplicationInfo 实例 ,即在桌面上显示每个应用程序图标,点击即可启动这些应用程序。
而点击最右边中间 MENU 按扭时由如下函数完成:
/**
* Launches the intent referred by the clicked shortcut.
*
* @param v The view representing the clicked shortcut.
*/
public void onClick(View v) {
showAllApps(true);
}
-->
void showAllApps(boolean animated) {
mAllAppsGrid.zoom(1.0f, animated);
((View) mAllAppsGrid).setFocusable(true);
((View) mAllAppsGrid).requestFocus();
// TODO: fade these two too
mDeleteZone.setVisibility(View.GONE);
}
将会显示系统中所有的应用,而点击具体的某个图标时:
AllApps2D.java @ AllApps2D.java
public void onItemClick(AdapterView parent, View v,
int position, long id) {
ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
mLauncher.startActivitySafely(app.intent, app);
}
调用 startActivitySafely 则启动相应的应用程序
总结:
这一节涉及到的东西太多太多,这里也只是简要的过了一下代码,还有很多的概念需要弄明白,但至少的知道其基本的流程步骤。
最后以一幅图结束android系统启动之框架: