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 内容:

  

  

  

  

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 apps) {

      mAllAppsGrid.setApps(apps);

}


6、AllApps2D.java 继续加载应用程序

public void setApps(ArrayList list) {

    mAllAppsList.clear();

    addApps(list);

}

public void addApps(ArrayList list){

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系统启动之框架:


你可能感兴趣的:(Android系统框架学习,android,学习及系统开发)