Android之ActivityManagerService詳解(APP啓動過程)

轉載請標明出處:【顧林海的博客】


前言

AMS(ActivityManagerService)的啓動是在SystemServer進程中啓動的,它的職責是用於和所有APP的四大組件進行通信,Activity的啓動過程就是APP端與AMS端進行通信,首先理解的一點是APP端與AMS是在兩個不同的進程中,因此APP端與AMS是通過跨進程通信的。

從Launcher啓動APP

Launcher就是指手機的屏幕,同時它也是一個APP,只不過這是由製造商開發的,手指點擊屏幕的某個APP,這時APP啓動並打開首頁的界面,這一系列操作需要和AMS進行通信才能完成,APP安裝(啓動)時,PackageManagerService從APK包的AndroidManifest文件中讀取四大組件的信息並保存下來。

下圖是Launcher與AMS的通信時序圖:

在這裏插入圖片描述

Launcher與APP是在兩個不同的進程中,他們之間的通信是通過Binder完成的,點擊Launcher上的某個APP,這時會調用Launcher的startActivitySafely方法。

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
    ...
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//1
    ...
    startActivity(intent, optsBundle);//2
    ...
}

上面代碼我省略了一些不太重要的,重點看上面兩行代碼,第一行給intent設置Flag爲Intent.FLAG_ACTIVITY_NEW_TASK,Activity會在新的任務棧中啓動,第二行代碼調用startActivity方法,很簡單,就是啓動APP中的Activity。

最終會調用Activity的startActivity方法,Intent中攜帶的就是需要啓動的APP的Activity信息。startActivity方法最終會調用startActivityForResult方法,代碼如下:

@Override
public void startActivity(Intent intent) {
   this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
   if (options != null) {
       startActivityForResult(intent, -1, options);
   } else {
       // Note we want to go through this call for compatibility with
       // applications that may have overridden the method.
       startActivityForResult(intent, -1);
   }
}



public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                  @Nullable Bundle options) {
   ...
   Instrumentation.ActivityResult ar =
           mInstrumentation.execStartActivity(
                   this, mMainThread.getApplicationThread(), mToken, this,
                   intent, requestCode, options);
   ...
}

Activity內部會保持一個對Instrumentation的引用,Instrumentation主要用來監控應用程序和系統的交互,在startActivityForResult方法中會調用Instrumentation的execStartActivity方法,在execStartActivity方法的第二個參數中,可以看到一個mMainThread的變量,這是一個ActivityThread類型的變量,ActivityThread就是主線程,也就是我們平常所說的UI線程,它是在APP啓動時創建的,代表APP應用程序,ActivityThread裏面有個main函數,是APP啓動時的入口。

execStartActivity方法傳遞了兩個很重要的參數,mMainThread.getApplicationThread(Binder對象)將Launcher所在的進程傳遞了過去,這樣AMS知道是哪個進程;還有一個比較重要的是mToken,它是Binder對象,代表Launcher這個Activity也通過Instrumentation傳給AMS,AMS查詢時,就知道誰向AMS發起了請求。

Instrumentation的execStartActivity代碼如下:

public Instrumentation.ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
   ...
    try {
        ...
        int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        ...
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

這裏通過ActivityManager的getService方法來獲取AMS的代理對象(Android 7.0是通過ActivityManagerNative的getDefault來獲取AMS的代理對象),返回一個類型爲IActivityManager,IActivityManager是一個接口,內部定義了四大組件的生命週期,

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

Singleton是一個單例類,內部通過ServiceManager取出一個activity的對象,通過IActivityManager.Stub.asInterface將它包裝成一個ActivityManagerProxy對象(AMP),IActivityManager.Stub.asInterface這段代碼是不是很熟悉,就是AIDL遠程代理,這裏獲取到的是AMS的代理對象。

AMP告訴AMS啓動哪個APP,並且啓動的是哪個Activity,AMS會檢查APP中的AndroidManifest文件,看看是否存在要啓動的Activity,如果不存在,就會拋出一個Activity not found的錯誤。AMS檢查到啓動的Activity存在,這時會告訴Launcher:“我要啓動Activity了”,Launcher會將它所在的進程傳給AMS,AMS會將它保存爲一個ActivityRecord對象,這個對象裏面有一個ApplicationThreadProxy,是一個Binder代理,AMS想要發送消息給Launcher,可以通過ApplicationThreadProxy(ATP)來發送消息,ATP是APP端ApplicationThread(APT)的代理對象,用於AMS與APP端的通信。

既然AMS知道了啓動的Activity,接下來就應該啓動Activity,在啓動Activity之前,AMS需要告訴Launcher“我要啓動了,你可以暫停了“,時序圖如下:

在這裏插入圖片描述

中間通過ApplicationThreadProxy向APP端的ApplicationThread發送消息,ApplicationThread接受到AMS的消息後,調用ActivityThread的sendMessage方法,向Launcher的主線程消息隊列發送一個PAUSE_ACTIVITY消息。

@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
                                int configChanges, PendingTransactionActions pendingActions, String reason) {
    //獲取Launcher的Activity
    ActivityClientRecord r = mActivities.get(token);
    if (r != null) {
        if (userLeaving) {
            performUserLeavingActivity(r);
        }

        r.activity.mConfigChangeFlags |= configChanges;
        performPauseActivity(r, finished, reason, pendingActions);

        // Make sure any pending writes are now committed.
        if (r.isPreHoneycomb()) {
            QueuedWork.waitToFinish();
        }
        mSomeActivitiesChanged = true;
    }
}

handlePauseActivity方法中從mActivities集合中,獲取Launcher的Activity並讓他休眠。

到這裏Launcher與AMS之間的通信就結束了,接下來的事情就是啓動APP中的Activity,因爲是首次啓動,APP的進程不存在,需要創建一個新的進程,需要調用Process.start方法,並且指定了ActivityThread的main函數爲入口函數:

int pid=Process.start("android.app.ActivityThread",
        mSimpleProcessManagement ? app.processName:gid,
        debugFlags,
        null);

爲新進程創建ActivityThread對象,也就是UI線程,同時執行入口函數main,其中創建一個主線程Looper,也就是MainLooper。

另外創建Application,主線程序會收到BIND_APPLICATION消息:

public void handleMessage(Message msg) {
    ...
    switch (msg.what) {
        case BIND_APPLICATION:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
            AppBindData data = (AppBindData)msg.obj;
            handleBindApplication(data);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
            ...
    }
    ...
}

根據傳遞過來的ApplicationInfo創建一個對應的LoadedApk對象,然後創建ContextImpl對象,接着通過反射創建目標Application,並調用attach方法,將ContextImpl對象設置爲目標Application的上下文環境,最後調用Application的onCreate函數。

創建完APP後,APP端通知AMS創建完畢同時把ActivityThread對象發送給AMS,同時AMS端把ActivityThread對象轉換成一個ActivityThreadProxy對象,之後AMS可以向APP端發送消息,通過ActivityThreadProxy這個代理對象。

在這裏插入圖片描述

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}

ActivityThread接受到AMS的消息,在H中發送LAUNCH_ACTIVITY消息,調用handleLaunchActivity方法,在該方法中通過Instrumentation的newActivity方法,創建要啓動的Activity實例,爲這個Activity創建一個上下文Context對象,並與Activity關聯,通過Instrumentation的callActivityOnCreate方法,執行Activity的onCreate方法,從而啓動Activity,至此APP啓動完畢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章