Activity啟動流程原始碼分析

HitenDev發表於2018-03-29

最近我開始學習framework,不想一上來就研究到c/c++層程式啟動原理什麼的,首先得從四大元件的啟動流程入手學習,所以我決定寫幾篇博文,來記錄整個過程的學習心得。

關於Activity的啟動流程,我準備分成兩個部分來寫:app程式篇和system程式篇,作為一個應用層開發者,其實掌握前者已經夠用了,第二篇作為提高,畢竟多瞭解一點也沒有壞處,就這樣吧。

Activity啟動流程原始碼分析

本文主要基於android8.1.0_r15程式碼分支除錯分析;

需要掌握的知識:

  • Activity生命週期
  • AIDL原理
  • Handler機制

一、從startActivity到AMS

我們都知道,開啟一個新的Activity需要呼叫startActivity方法,該方法定義在Context中的,並且在Activity中做了重寫,如果是在Service中開啟一個Activity呢,Service的實現來自Context,先分析在Context中的實現。

1.1 在ContextImpl中startActivity實現;

ContextImpl#startActivity

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

@Override
public void startActivity(Intent intent, Bundle options) {
    warnIfCallingFromSystemProcess();
    if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
            && options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
        throw new AndroidRuntimeException(
                "Calling startActivity() from outside of an Activity "
                + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                + " Is this really what you want?");
    }
    //真正的呼叫在這裡
    mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity) null, intent, -1, options);
}
複製程式碼

順手看一眼Activity中是怎樣實現的(fk,你到底眼看的還是手看的);

1.2 Activity中是startActivity實現

Activity#startActivity

@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 {
        startActivityForResult(intent, -1);
    }
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        //真正的呼叫在這裡
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}
複製程式碼

比較Activity和ContextImpl的區別:

最終都是呼叫Instrumentation.execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)方法,然後就是ContextImpl下有幾個引數傳null。

此外,Context還定義startActivityAsUser方法,該方法對應用層是隱藏的,最終也呼叫Instrumentation.execStartActivity另一個過載方法,暫不追蹤另一個方法。那我們繼續跟進Instrumentation程式碼。

1.3 Instrumentation中execStartActivity

注意:Instrumentation下,execStartActivity有幾個過載方法,我們這裡只分析有七個引數,且第四個引數為Activity型別的execStartActivity方法

Instrumentation#execStartActivity

public ActivityResult execStartActivity(
       Context who, IBinder contextThread, IBinder token, Activity target,
       Intent intent, int requestCode, Bundle options) {
   IApplicationThread whoThread = (IApplicationThread) contextThread;
   Uri referrer = target != null ? target.onProvideReferrer() : null;
   if (referrer != null) {
       intent.putExtra(Intent.EXTRA_REFERRER, referrer);
   }
   if (mActivityMonitors != null) {
       synchronized (mSync) {
           final int N = mActivityMonitors.size();
           for (int i=0; i<N; i++) {
               final ActivityMonitor am = mActivityMonitors.get(i);
               ActivityResult result = null;
               if (am.ignoreMatchingSpecificIntents()) {
                   result = am.onStartActivity(intent);
               }
               if (result != null) {
                   am.mHits++;
                   return result;
               } else if (am.match(who, null, intent)) {
                   am.mHits++;
                   if (am.isBlocking()) {
                       return requestCode >= 0 ? am.getResult() : null;
                   }
                   break;
               }
           }
       }
   }
   try {
       intent.migrateExtraStreamToClipData();
       intent.prepareToLeaveProcess(who);
       //真正的呼叫在這裡
       int result = ActivityManager.getService()
           .startActivity(whoThread, who.getBasePackageName(), intent,
                   intent.resolveTypeIfNeeded(who.getContentResolver()),
                   token, target != null ? target.mEmbeddedID : null,
                   requestCode, 0, null, options);
       checkStartActivityResult(result, intent);
   } catch (RemoteException e) {
       throw new RuntimeException("Failure from system", e);
   }
   return null;
}
複製程式碼

我們先捋清每個引數的意義

引數名 引數型別 意義
who Context 上下文物件
contextThread IBinder ApplicationThread物件
token IBinder 當前Activity的Token,可能為空
target Activity 當前Activity,可能為空
intent Intent intent
requestCode int startActivityforResult傳的requestCode
options Bundle 傳遞的資料

這七個引數最不熟悉的就是token和contextThread,這兩個是IBinder型別,這個問題先放一放,帶著疑問,我們繼續往下看ActivityManager.getService()是什麼鬼。

1.4 ActivityManager和AMS

ActivityManager#getService

//獲取的是一個單例物件
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);
                //正在的IActivityManager在這裡
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };
複製程式碼

getService()返回是從IActivityManagerSingleton單例物件中得到,真正的操作是IActivityManager.Stub,就這兩行程式碼

final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
複製程式碼

Stub這貨是AIDL生成的,關於AIDL原理自行學習,我們從AIDL生成的程式碼裡拿到了IActivityManager代理物件,然後再回到Instrumentation.execStartActivity繼續看

真正呼叫的是IActivityManager.startActivity()方法,AIDL應該該有的東西。我們還是分析一下IActivityManager.aidl檔案怎樣定義該方法的。

frameworks/base/core/java/android/app/IActivityManager.aild

int startActivity(in IApplicationThread caller, in String callingPackage, in Intent intent,
            in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
            int flags, in ProfilerInfo profilerInfo, in Bundle options);
複製程式碼

這個方法一共十個引數,但是沒有註釋,我們看看呼叫端Instrumentation怎麼傳參的吧。

引數名 傳參值 意義
caller whoThread ApplicationThread物件
callingPackage who.getBasePackageName() 應用包名
intent intent
resolvedType intent.resolveTypeIfNeeded(who.getContentResolver()) Return the MIME data type of this intent
resultTo token 呼叫者,也就是結果將要返給誰
resultWho target != null ? target.mEmbeddedID : null 呼叫者的另一種標識吧
requestCode requestCode
flags 0
ProfilerInfo null
Bundle options

寫的馬馬虎虎湊合看一下吧,其實很好理解。

那麼IActivityManager真正的Stub是誰呢,按照AIDL的慣例,肯定是繼承它的IActivityManager.Stub,一番搜尋,我們找到了ActivityManagerService這個類。

frameworks/base/service/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}
複製程式碼

WMS我們暫時不再往下追蹤,因為已經超出這篇文章的提綱了,先記住這個類方法入口,我們下篇將要從這裡分析,到這我畫一張圖,總結一下上面說的這些。

Activity啟動流程原始碼分析

圖畫的很簡單,值得注意的是綠色代表執行在system_process程式,system_process就是AMS所在的程式。

二、ActivityThread分析

上文我們一直提到一個型別IApplicationThread,在Activity和ContextImpl中傳值是mMainThread.getApplicationThread()mMainThreadActivityThread型別,getApplicationThread得到了ApplicationThread,那我們重點分析ApplicationThreadActivityThread這兩個物件。

2.1 main方法入口

首先,ActivityThread並沒有繼承Thread,那它就不是執行緒的子類,那它代表了什麼,從官方的註釋的來看,他是一個應用程式主執行緒執行的管理者,負責排程和執行四大元件,著手分析他,我們從main方法入口。

ActivityThread#main

    public static void main(String[] args) {
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
    }
複製程式碼

精簡完程式碼可以看出,main方法中呼叫Looper.prepareMainLooperf方法,該方法建立主執行緒的Looper物件,緊接著建立ActivityThread物件並呼叫attach方法,attach方法引數system用來區分是否是系統程式,我們先不考慮系統程式

2.2 attach方法

ActivityThread#attach

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        //獲取IActivityManager代理物件
        final IActivityManager mgr =ActivityManager.getService();
        try {
            //呼叫attachApplication方法
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    } 
}
複製程式碼

上面關於system的和ViewRootImpl相關的程式碼已經精簡掉,可以清楚的看到呼叫IActivityManagerattachApplication方法,上文已經提到過startActivity方法也是類似,但是巧合的是兩個方法都傳遞了IApplicationThread物件作為第一個引數,上面傳遞的是mAppThread,那麼這個mAppThread和IApplicationManager何種關係?

2.3 ApplicationThread分析

ApplicationThread繼承自IApplicationThread.Stub,說到這裡大家可能就尬笑了,又是AIDL,先看一下它定義哪些引數,放眼望去大部分是schedule開頭的方法 ApplicationThread#scheduleLaunchActivity

@Override
public final void scheduleLaunchActivity(Intenintent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfigConfiguration overrideConfig,
        CompatibilityInfo compatInfo, Strinreferrer, IVoiceInteractor voiceInteractor,
        int procState, Bundle statePersistableBundle persistentState,
        List<ResultInfo> pendingResultsList<ReferrerIntent> pendingNewIntents,
        boolean notResumed, boolean isForwardProfilerInfo profilerInfo) {
    updateProcessState(procState, false);
    ActivityClientRecord r = neActivityClientRecord();
    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.referrer = referrer;
    r.voiceInteractor = voiceInteractor;
    r.activityInfo = info;
    r.compatInfo = compatInfo;
    r.state = state;
    r.persistentState = persistentState;
    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;
    r.startsNotResumed = notResumed;
    r.isForward = isForward;
    r.profilerInfo = profilerInfo;
    r.overrideConfig = overrideConfig;
    updatePendingConfiguration(curConfig);
    sendMessage(H.LAUNCH_ACTIVITY, r);
}
複製程式碼

方法太多不貼上了,但是有個類有必要留意一下,那就是ActivityClientRecord

2.3.1 ActivityClientRecord.token意義:

ActivityClientRecord名字為啥帶個client,我認為是為了區別AMS的,ActivityThread相對於AMS就是client;

再顧名思義,這個類是客戶端記錄Activity資訊的,有個關鍵屬性token,token在前文出現過,但是這裡出現意義不一樣,為啥,因為這個從WMS傳遞過來的,這是來源,其實在system_process中並不會生成正在的Activity物件,那如何在app端和system_process中共同標識唯一的Activity呢,就是這個token。

再回歸到scheduleLaunchActivity方法,最後呼叫了 sendMessage()方法;追蹤該方法,最終呼叫mH的sendMessage方法 ApplicationThread#sendMessage

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
    msg.setAsynchronous(true);
    }
    //真正的大佬
    mH.sendMessage(msg);
}
複製程式碼

那麼mH又是誰,是H,繼承自Handler,一個H單字母好風騷,H是幹啥的呢,主要進行執行緒間通訊,主要看它的handleMessage方法

2.4 H類

ActivityThread.H

 public static final int LAUNCH_ACTIVITY         = 100;
 public static final int PAUSE_ACTIVITY          = 101;
 public static final int PAUSE_ACTIVITY_FINISHING= 102;
 ...

 public void handleMessage(Message msg) {
     if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
     switch (msg.what) {
         case LAUNCH_ACTIVITY: {
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
             final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

             r.packageInfo = getPackageInfoNoCheck(
                     r.activityInfo.applicationInfo, r.compatInfo);
             handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         } break;
}
複製程式碼

程式碼太長少貼上為妙,反正是定義一堆常量,然後handleMessage一路的switch case,很有規律的最終呼叫ActivityThread下名字handleXXX()的方法;

隨便進入一個比如handleLaunchActivity方法,下面貌似是建立Activity的程式碼,對建立Activity的程式碼就是這裡。 既然找到了Activity的建立入口,我們是不是趁著興奮一路進入handleLaunchActivity看個究竟;說得對,但是我想回過頭來捋一下這幾個類的關係ActivityThread,H,ApplicationThread,IApplicationThread,IActivityManager;

2.5 ActivityThread & ApplicationThread & ActivityManagerService關係

先說ApplicationThreadActivityManagerService程式間雙向通訊:

分析這兩個之前,必須得了解AIDL的Proxy/Stub模式,Proxy作為客戶端的代理物件,Stub作為服務端的存根(真正實現),IActivityManager和IApplicationThread兩者實現binder雙向通訊。

當app程式向system_process程式請求startActivity事,app程式從ActivityManager得到IActivityManager的Proxy物件,system_process程式正真的Stub是ActivityManagerService;

當system_process向app程式答覆這個請求時,此時app程式作為服務端,system_process呼叫IApplicationThread的proxy物件,app程式正真的Stub是ApplicationThread,從而實現了兩者的雙向通訊。

IActivityManager和IApplicationThread

再說ActivityThreadApplicationThread執行緒間通訊:

為什麼說這兩個哥們是需要執行緒通訊,上文得知ActivityThread是程式碼主執行緒,ApplicationThread代表app程式的IApplicationThread.Stub;

這兩者跟執行緒有什麼關係,這就涉及到binder的另一個知識binder執行緒池,具體不在這裡描述,記住一點ApplicationThrea裡面的方法都是在binder執行緒中執行的,所以H這個類應運而生,接管這兩者之間的執行緒通訊。呵呵我有圖。

Activity啟動流程原始碼分析

三、Activity從建立到顯示經歷了什麼

接前文所講,我們繼續從handleLaunchActivity方法分析,探究Activity的建立和啟動。

3.1 分析handleLaunchActivity()

ActivityThread#handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;
    if (r.profilerInfo != null) {
        mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();
    }
    // Make sure we are running with the most recent config.
    handleConfigurationChanged(null, null);
    if (localLOGV) Slog.v(
    TAG, "Handling launch of " + r);
    // Initialize before creating the activity
    if (!ThreadedRenderer.sRendererDisabled) {
    GraphicsEnvironment.earlyInitEGL();
    }
    WindowManagerGlobal.initialize();
    //呼叫performLaunchActivity方法返回Activity物件
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        //呼叫resume方法
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    if (!r.activity.mFinished && r.startsNotResumed) {
            performPauseActivityIfNeeded(r, reason);
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
    }
複製程式碼

流程解析:

  1. 真正建立Activity的地方是在performLaunchActivity方法中
  2. 如果a不為空,呼叫handleResumeActivity執行resume,如果需要,呼叫performPauseActivityIfNeeded
  3. 如果a為空,通知AMS關閉該Activity

3.2 分析performLaunchActivity()

ActivityThread#performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }
    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
            mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }
    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName,
                r.activityInfo.targetActivity);
    }
    //建立ContextImpl
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        //類載入器
        java.lang.ClassLoader cl = appContext.getClassLoader();
        //建立Activity
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }
    try {
        //得到Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
        if (localLOGV) Slog.v(
                TAG, r + ": app=" + app
                + ", appName=" + app.getPackageName()
                + ", pkg=" + r.packageInfo.getPackageName()
                + ", comp=" + r.intent.getComponent().toShortString()
                + ", dir=" + r.packageInfo.getAppDir());
        if (activity != null) {
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (r.overrideConfig != null) {
                config.updateFrom(r.overrideConfig);
            }
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            Window window = null;
            if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                window = r.mPendingRemoveWindow;
                r.mPendingRemoveWindow = null;
                r.mPendingRemoveWindowManager = null;
            }
            //ContextImpl和Activity繫結
            appContext.setOuterContext(activity);
            //呼叫Activity的attath方法
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);
            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            checkAndBlockForNetworkAccess();
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }
            activity.mCalled = false;
            //呼叫Instrumentation.callActivityOnCreate()
            if (r.isPersistable()) {
                 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            if (!r.activity.mFinished) {
                //呼叫performStart
                activity.performStart();
                r.stopped = false;
            }
            //條件呼叫Instrumentation.callActivityOnRestoreInstanceState()
            if (!r.activity.mFinished) {
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            //條件呼叫Instrumentation.callActivityOnPostCreate()
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;
        //講Activity放到集合中
        mActivities.put(r.token, r);
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }
    return activity;
}
複製程式碼

在performLaunchActivity方法中做的工作挺多,我們整理一下關鍵的流程

  1. 建立ContextImpl
  2. 呼叫mInstrumentation.newActivity()返回Activity物件
  3. 得到Application物件
  4. 將Activity關聯到ContextImpl
  5. 呼叫Activity的attach()方法
  6. 呼叫Instrumentation.callActivityOnCreate()
  7. !mFinished呼叫activity.performStart();
  8. !mFinished呼叫Instrumenation.callActivityOnRestoreInstanceState
  9. !mFinished呼叫Instrumentation.callActivityOnPostCreate()
  10. 把Activity物件加入到集合中 我們逐一分析

3.3 ContextImpl建立

ActivityThread#createBaseContextForActivity

private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
    final int displayId;
    try {
        displayId = ActivityManager.getService().getActivityDisplayId(r.token);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
    //建立ContextImpl
    ContextImpl appContext = ContextImpl.createActivityContext(
            this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
    final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
    String pkgName = SystemProperties.get("debug.second-display.pkg");
    if (pkgName != null && !pkgName.isEmpty()
            && r.packageInfo.mPackageName.contains(pkgName)) {
        for (int id : dm.getDisplayIds()) {
            if (id != Display.DEFAULT_DISPLAY) {
                Display display =
                        dm.getCompatibleDisplay(id, appContext.getResources());
                appContext = (ContextImpl) appContext.createDisplayContext(display);
                break;
            }
        }
    }
    return appContext;
}
複製程式碼

ContextImpl的真正建立是呼叫ContextImpl.createActivityContext,接下來又要分析Instrumentation這個傢伙了

3.4 再次分析Instrumentation

Instrumentation#newActivity

public Activity newActivity(ClassLoader cl, String className,
        Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
        //反射呼叫
    return (Activity)cl.loadClass(className).newInstance();
}
複製程式碼

Instrumentation#callActivityOnCreate

 public void callActivityOnCreate(Activity activity, Bundle icicle) {
     prePerformCreate(activity);
     activity.performCreate(icicle);
     postPerformCreate(activity);
 }
複製程式碼

Instrumentation#callActivityOnRestoreInstanceState

public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
    activity.performRestoreInstanceState(savedInstanceState);
}
複製程式碼

Instrumentation#callActivityOnPostCreate

public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
    activity.onPostCreate(icicle);
}
複製程式碼

Instrumentation大部分起到一箇中轉作用,真正還是呼叫了Activity的相關方法,所以最終程式碼歸結到Activity身上。

3.5 分析performResumeActivity()

再回到handleLaunchActivity的第二步呼叫handleResumeActivity,handleResumeActivity方法會繼續呼叫performResumeActivity

ActivityThread#performResumeActivity

public final ActivityClientRecord performResumeActivity(IBinder token,
        boolean clearHide, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    if (localLOGV) Slog.v(TAG, "Performing resume of " + r
            + " finished=" + r.activity.mFinished);
    if (r != null && !r.activity.mFinished) {
        if (clearHide) {
            r.hideForNow = false;
            r.activity.mStartedActivity = false;
        }
        try {
            r.activity.onStateNotSaved();
            r.activity.mFragments.noteStateNotSaved();
            checkAndBlockForNetworkAccess();
            if (r.pendingIntents != null) {
                deliverNewIntents(r, r.pendingIntents);
                r.pendingIntents = null;
            }
            if (r.pendingResults != null) {
                deliverResults(r, r.pendingResults);
                r.pendingResults = null;
            }
            //呼叫在這裡
            r.activity.performResume();

            synchronized (mResourcesManager) {
                for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
                    final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
                    if (relaunching.token == r.token
                            && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
                        relaunching.startsNotResumed = false;
                    }
                }
            }
            EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(),
                    r.activity.getComponentName().getClassName(), reason);
            r.paused = false;
            r.stopped = false;
            r.state = null;
            r.persistentState = null;
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException(
                    "Unable to resume activity "
                    + r.intent.getComponent().toShortString()
                    + ": " + e.toString(), e);
            }
        }
    }
    return r;
}
複製程式碼

這裡關鍵點是呼叫Activity.performResume方法; 繼續解析handleResumeActivity()方法

3.6 分析handleResumeActivity()

ActivityTread#handleResumeActivity

final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
        return;
    }
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;
    // TODO Push resumeArgs into the activity for consideration
    //最終會呼叫activity的performResume()
    r = performResumeActivity(token, clearHide, reason);
    if (r != null) {
        final Activity a = r.activity;
        if (localLOGV) Slog.v(
            TAG, "Resume " + r + " started activity: " +
            a.mStartedActivity + ", hideForNow: " + r.hideForNow
            + ", finished: " + a.mFinished);
        final int forwardBit = isForward ?
                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
        // If the window hasn't yet been added to the window manager,
        // and this guy didn't finish itself or start another activity,
        // then go ahead and add the window.
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) {
            try {
                willBeVisible = ActivityManager.getService().willActivityBeVisible(
                        a.getActivityToken());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        if (r.window == null && !a.mFinished && willBeVisible) {
            //獲取到window
            r.window = r.activity.getWindow();
            //docor設定成INVISIBLE狀態
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    //把decorView假如wm
                    wm.addView(decor, l);
                } else {
                    a.onWindowAttributesChanged(l);
                }
            }
        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(
                TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }
        // Get rid of anything left hanging around.
        cleanUpPendingRemoveWindows(r, false /* force */);
        // The window is now visible if it has been added, we are not
        // simply finishing, and we are not starting another activity.
        if (!r.activity.mFinished && willBeVisible
                && r.activity.mDecor != null && !r.hideForNow) {
            if (r.newConfig != null) {
                performConfigurationChangedForActivity(r, r.newConfig);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                        + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                r.newConfig = null;
            }
            if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                    + isForward);
            WindowManager.LayoutParams l = r.window.getAttributes();
            if ((l.softInputMode
                    & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                    != forwardBit) {
                l.softInputMode = (l.softInputMode
                        & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                        | forwardBit;
                if (r.activity.mVisibleFromClient) {
                    //decorView更新wm
                    ViewManager wm = a.getWindowManager();
                    View decor = r.window.getDecorView();
                    wm.updateViewLayout(decor, l);
                }
            }
            r.activity.mVisibleFromServer = true;
            mNumVisibleActivities++;
            if (r.activity.mVisibleFromClient) {
                r.activity.makeVisible();
            }
        }
        if (!r.onlyLocalRequest) {
            r.nextIdle = mNewActivities;
            mNewActivities = r;
            if (localLOGV) Slog.v(
                TAG, "Scheduling idle handler for " + r);
            Looper.myQueue().addIdleHandler(new Idler());
        }
        r.onlyLocalRequest = false;
        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                //通知AMS這個activity更新了狀態
               ActivityManager.getService().activityResumed(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    } else {
        //異常情況,幹掉AMS的記錄
        try {
            ActivityManager.getService()
                .finishActivity(token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}
複製程式碼

3.7 Activity顯示和WindowManager繼承

activity真正的顯示是邏輯是windowManager.add(View,WindowManager.LayoutParams),WindowManager從Activity獲取,Activity從Window得到,分析Window程式碼得到WindowManagerImpl是真正的實現,確定麼?

在看WindowManagerImpl程式碼,我曹真正的實現是WindowManagerGlobal,順藤摸瓜到WindowManagerGlobal.addView方法,發現WindowManagerGlobal也只是記錄記錄view的資訊,真正處理View的ViewRootImpl物件。

WindowManager.addView追蹤: Activity->Window->WindowManagerImpl->WindowManagerGlobal->ViewRootImpl.setView(),END;

3.8 小結

回到主題,總結一下Activity相關方法被呼叫的順序 0. 反射構造

  1. attach()
  2. performCreate()
  3. performStart()
  4. performRestoreInstanceState()
  5. onPostCreate()
  6. performResume()

Activity顯示關鍵程式碼順序:

  1. activity.performResume()
  2. ViewRootImpl.setView() 發問,Activity執行onResume的時候,真是已經展示在螢幕上了嗎?

現在我們可以很輕鬆的得到從AMS到Activity的啟動時序圖:

Activity啟動流程原始碼分析

總結

洋洋灑灑寫了一篇,整體沒有多大的深度,是以Activity的啟動為主線,記錄了在app程式中Activity啟動的呼叫過程,但是沒有講到Activity其他生命週期的相關呼叫,沒有講到Activity自身呼叫的流程,算是遺憾吧。

另外:近期想寫兩篇VirtualApk的原始碼解析(包括gradle_plugin),到時應該會涉及到更詳細更具體的知識點了,加油吧!

相關文章