第一个Apk程序的启动

来源:互联网 发布:sap hana数据库优势 编辑:程序博客网 时间:2024/06/08 05:03
Ams启动分析
上节介绍了ZygoteInit.java 启动后加载了若干服务但是我们看到手机启动后显示的是一个Activity 也就是系统启动的第一个apk程序 那么这个apk是怎么样启动的呢
此文就是探索下这个奥秘。在柯元旦老师的文章中提到过当 Ams启动成功后在会发送一个Intent来启动第一个程序,通过阅读代码确实如此!

首先来看下 Ams程序吧。Ams的入口程序为 main函数


public static final Context main(int factoryTest) {        AThread thr = new AThread();        thr.start();        synchronized (thr) {            while (thr.mService == null) {                try {                    thr.wait();                } catch (InterruptedException e) {                }            }        }        ActivityManagerService m = thr.mService;        mSelf = m;        ActivityThread at = ActivityThread.systemMain();        mSystemThread = at;        Context context = at.getSystemContext();        m.mContext = context;        m.mFactoryTest = factoryTest;        PowerManager pm =            (PowerManager)context.getSystemService(Context.POWER_SERVICE);        m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");        m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");        m.mLaunchingActivity.setReferenceCounted(false);                m.mBatteryStatsService.publish(context);        m.mUsageStatsService.publish(context);                synchronized (thr) {            thr.mReady = true;            thr.notifyAll();        }        m.startRunning(null, null, null, null);                return context;    }


在此函数中首先实例了 AThread 类,从名字看这个类是个线程类,Ams的实例就是是在此类中new的。

 static class AThread extends Thread {        ActivityManagerService mService;        boolean mReady = false;        public AThread() {            super("ActivityManager");        }        public void run() {            Looper.prepare();            android.os.Process.setThreadPriority(                    android.os.Process.THREAD_PRIORITY_FOREGROUND);            ActivityManagerService m = new ActivityManagerService();            synchronized (this) {                mService = m;                notifyAll();            }            synchronized (this) {                while (!mReady) {                    try {                        wait();                    } catch (InterruptedException e) {                    }                }            }            Looper.loop();        }    }

从代码中可以看到 线程还创建了一个Looper,AThread线程启动以后等待Ams 的实例完成,然后进入Looper循环。Ams 实例完成后通过ActivityThread.getSystemContext()获取一个Context,这个context是个ApplicationContext 然后在获去PowerManager、至此Ams的实例准本工作基本完成。在main方法最后调用startRunning方法

public final void startRunning(String pkg, String cls, String action,            String data) {        synchronized(this) {            if (mStartRunning) {                return;            }            mStartRunning = true;            mTopComponent = pkg != null && cls != null                    ? new ComponentName(pkg, cls) : null;            mTopAction = action != null ? action : Intent.ACTION_MAIN;            mTopData = data;            if (!mSystemReady) {                return;            }        }        systemReady(null);    }

哈这里主要设置了
mTopComponent 
mTopAction 
mTopData 
当然最重要的是mTopAction,mTopAction被设置成了 Intent.ACTION_MAIN

然后继续调用了systemReady(null);

在systemReady中最后调用了 resumeTopActivityLocked(null);

private final boolean resumeTopActivityLocked(HistoryRecord prev) {        // Find the first activity that is not finishing.        HistoryRecord next = topRunningActivityLocked(null);        // Remember how we'll process this pause/resume situation, and ensure        // that the state is reset however we wind up proceeding.        final boolean userLeaving = mUserLeaving;        mUserLeaving = false;        if (next == null) {            // There are no more activities!  Let's just start up the            // Launcher...            return startHomeActivityLocked();        }       ......         ....省略很多代码}

由于Ams刚启动所以mHistory里面没有HistoryRecord记录这样就会调用startHomeActivityLocked()方法 手机的第一apk程序正是在这里实现的启动的。

 private boolean startHomeActivityLocked() {        if (mFactoryTest == SystemServer.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 = new Intent(            mTopAction,            mTopData != null ? Uri.parse(mTopData) : null);        intent.setComponent(mTopComponent);        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {            intent.addCategory(Intent.CATEGORY_HOME);        }        ActivityInfo aInfo =            intent.resolveActivityInfo(mContext.getPackageManager(),                    STOCK_PM_FLAGS);        if (aInfo != null) {            intent.setComponent(new ComponentName(                    aInfo.applicationInfo.packageName, aInfo.name));            // Don't do this if the home app is currently being            // instrumented.            ProcessRecord app = getProcessRecordLocked(aInfo.processName,                    aInfo.applicationInfo.uid);            if (app == null || app.instrumentationClass == null) {                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);                startActivityLocked(null, intent, null, null, 0, aInfo,                        null, null, 0, 0, 0, false, false);            }        }                        return true;    }

在这里通过PackageManager搜索到了Action为 Intent.ACTION_MAIN ,Category为Intent.CATEGORY_HOME的Activity,并且启动搜索到的Activity就可以了。至此第一要启动的

Activity就找到并且启动了.

只要我们在自己的activity中加入

 <intent-filter >
                <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.HOME" />
               
            </intent-filter>

也可以成为第一启动的程序


这里我是在android_2.1的源码中调试跟踪的

我还下载了4.0的源码 4.0 与2.1的源码并不一样但是 意思是一样的 4.0多了一个ActivityStack包装类 2.1中关于Activity的处理都放到了 ActivityStack Ams更像一个代理了