Android 7.0 startActivity()源碼解析以及對幾個問題的思考:

1、本文須要解決的問題

本文並非很是詳細地解釋startActivity()源碼每行代碼的具體做用(實際上也根本作不到),因此我省略了不少代碼,只保留了最核心的代碼。我研究這段源碼的目的是爲了解決如下幾個我在開發應用的過程當中所思考的問題:java

  1. 是經過何種方式生成一個新的Activity類的,是經過java反射生成的嗎?
  2. Activity的生命週期回調方法是經過哪一個類調用的,在何時調用的?
  3. 界面的繪製是在執行Activity#onResume()以後仍是以前?
  4. 在以前的學習中,我瞭解到應用程序的真正入口是ActivityThread類,那麼ActivityThread#main()方法是在哪裏調用的?

2、相關解析(基於Android 7.1源碼)

// 這裏解析的是在已有進程中啓動一個新Activity的狀況
Intent intent = new Intent(this, SubActivity.class);
intent.startActivity();
複製代碼

(1)Activity本地調用: Activity#startActivity()   --> Activity#startActivityForResult()android

@Override
public void startActivityForResult(String who, Intent intent, int requestCode, @Nullable Bundle options) {
    // 省略代碼
    Instrumentation.ActivityResult ar = 
                mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, who,
                intent, requestCode, options);
    // 省略代碼
}
複製代碼

(2)Instrumentation#execStartActivity Instrumentation類至關於一個管家,它的職責是管理各個應用程序和系統的交互,Instrumentation將在任何應用程序運行前初始化,每一個進程只會存在一個Instrumentation對象,且每一個Activity都有此對象的實際引用,能夠經過它監測系統與應用程序之間的全部交互。設計模式

public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
    // 省略代碼
    int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
    checkStartActivityResult(result, intent);
    // 省略代碼
}
複製代碼

(3)ActivityManagerNative,ActivityManagerService,ActivityManagerProxy類之間的關係 ActivityManagerNative#getDefault()   --> ActivityManagerProxy#startActivity()服務器

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    data.writeString(callingPackage);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo);
    data.writeString(resultWho);
    data.writeInt(requestCode);
    data.writeInt(startFlags);
    if (profilerInfo != null) {
        data.writeInt(1);
        profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        data.writeInt(0);
    }
    if (options != null) {
        data.writeInt(1);
        options.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
    reply.readException();
    int result = reply.readInt();
    reply.recycle();
    data.recycle();
    return result;
}
複製代碼

若是學過AIDL的話,對上面這段代碼會比較熟悉,其實上面是發起了一次跨進程調用。這裏涉及到一種設計模式叫做代理模式,這裏不詳細介紹這種設計模式,簡單總結一下:app

  • ActivityManagerProxy至關於Proxy
  • ActivityManagerNative就至關於Stub
  • ActivityManagerService是ActivityManagerNative的具體實現,換句話說,就是AMS纔是服務端的具體實現!

(4)ActivityMangerService ActivityMangerService#startActivity()   --> ActivityMangerService#startActivityAsUser()socket

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null);
}
複製代碼

(5)ActivityStarter ActivityStarter類的註釋:ide

/** * Controller for interpreting how and then launching activities. * * This class collects all the logic for determining how an intent and flags should be turned into * an activity and associated task and stack. */
複製代碼

簡單來講,ActivityStarter類主要負責處理Activity的Intent和Flags, 還有關聯相關的Stack和TaskRecord ActivityStarter#startActivityMayWait()   --> ActivityStarter#startActivityLocked()     --> ActivityStarter#startActivityUnchecked()函數

其中: **startActivityMayWait():**獲取Activity的啓動信息,包括ResolveInfo和ActivityInfo,以及獲取CallingPid和CallingUid; **startActivityLocked():**建立一個ActivityRecord; **startActivityUnchecked():**設置TaskRecord, 完成後執行ActivityStackSupervisor類的resumeFocusedStackTopActivityLocked方法oop

(6)ActivityStackSupervisor和ActivityStack ActivityStackSupervisor#resumeFocusedStackTopActivityLocked()   --> ActivityStackSupervisor#resumeTopActivityUncheckedLocked()     --> ActivityStack#resumeTopActivityInnerLocked()       --> ActivityStackSupervisor#startSpecificActivityLocked()post

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

    r.task.stack.setLaunchTime(r);

    if (app != null && app.thread != null) {
         try {
             if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                 // Don't add this if it is a platform component that is marked
                 // to run in multiple processes, because this is actually
                 // part of the framework so doesn't make sense to track as a
                 // separate apk in the process.
                 app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
             }
             // !!!
             realStartActivityLocked(r, app, andResume, checkConfig);
             return;
        } catch (RemoteException e) {
             Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
    }

    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
}
複製代碼

這裏會判斷進程是否存在,因爲咱們是在原有進程中啓動一個新的activity,因此會調用 realStartActivityLocked()方法。 ActivityStackSupervisor#realStartActivityLocked()

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
    // 省略代碼
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
}  
複製代碼

(7)關於IApplicationThread,ApplicationThreadProxy,ApplicationThreadNative,ApplicationThread 上述代碼中,app.thread爲IApplicationThread類型,繼承了IInterface,咱們查看IApplicationThread的直接實現ApplicationThreadNative ApplicationThreadNative#scheduleLaunchActivity()

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException {
    Parcel data = Parcel.obtain();
    data.writeInterfaceToken(IApplicationThread.descriptor);
    intent.writeToParcel(data, 0);
    data.writeStrongBinder(token);
    data.writeInt(ident);
    info.writeToParcel(data, 0);
    curConfig.writeToParcel(data, 0);
    if (overrideConfig != null) {
        data.writeInt(1);
        overrideConfig.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }
    compatInfo.writeToParcel(data, 0);
    data.writeString(referrer);
    data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
    data.writeInt(procState);
    data.writeBundle(state);
    data.writePersistableBundle(persistentState);
    data.writeTypedList(pendingResults);
    data.writeTypedList(pendingNewIntents);
    data.writeInt(notResumed ? 1 : 0);
    data.writeInt(isForward ? 1 : 0);
    if (profilerInfo != null) {
        data.writeInt(1);
        profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        data.writeInt(0);
    }
    mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
    data.recycle();
}
複製代碼

一樣的,這裏也發起了一次跨進程調用。

  • ApplicationThreadProxy至關於Proxy
  • ApplicationThreadNative至關於Stub
  • ApplicationThread至關於服務器端,代碼真正的實現者!

(8)ActivityThread.ApplicationThread類 ActivityThread.ApplicationThread#scheduleLaunchActivity

@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

    updateProcessState(procState, false);

    ActivityClientRecord r = new ActivityClientRecord();

    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);
}
複製代碼

這裏會調用sendMessage,最後調用到mH.sendMessage(msg); mH爲H類的一個實例,H就是Handler的一個子類,發送消息以後,咱們來查看H類的handleMessage()方法: 源碼裏面就是根據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);
} 
複製代碼

(9) 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
    WindowManagerGlobal.initialize();
        
    // !!!
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

        if (!r.activity.mFinished && r.startsNotResumed) {
            // The activity manager actually wants this one to start out paused, because it
            // needs to be visible but isn't in the foreground. We accomplish this by going
            // through the normal startup (because activities expect to go through onResume()
            // the first time they run, before their window is displayed), and then pausing it.
            // However, in this case we do -not- need to do the full pause cycle (of freezing
            // and such) because the activity manager assumes it can just retain the current
            // state it has.
            performPauseActivityIfNeeded(r, reason);

            // We need to keep around the original state, in case we need to be created again.
            // But we only do this for pre-Honeycomb apps, which always save their state when
            // pausing, so we can not have them save their state when restarting from a paused
            // state. For HC and later, we want to (and can) let the state be saved as the
            // normal part of stopping the activity.
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
     } else {
         // If there was an error, for any reason, tell the activity manager to stop us.
         try {
             ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
     }
}
複製代碼

這裏會調用performLaunchActivity()方法。

(10)ActivityThread#performLaunchActivity()

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
    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);
    }

    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        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 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) {
            Context appContext = createBaseContextForActivity(r, activity);
            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;
            }
            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);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            if (r.isPersistable()) {
                // 11.1
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                // 11.1
                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) {
                // 11.2
                activity.performStart();
                r.stopped = false;
            }
            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);
                }
            }
            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;

        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;
}
複製代碼

這裏會收集要啓動的Activity的相關信息,主要是package和component信息,而後經過ClassLoader將要啓動的Activity類加載出來。

這裏就解決了個人第一個問題:新的Activity類是經過類加載器方式即經過反射的方式生成的,咱們能夠看一下mInstrumentation.newActivity()方法:

public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
}
複製代碼

最後調用mInstrumentation.callActivityOnCreate()

(11) 11.1 Instrumentation#callActivityOnCreate()

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

Activity#performCreate()

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    restoreHasCurrentPermissionRequest(icicle);
    onCreate(icicle, persistentState);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}
複製代碼

這裏就會顯式調用Activity的生命週期方法onCreate()!

11.2 Activity#performStart()

final void performStart() {
    // 省略代碼
    // !!!
    mInstrumentation.callActivityOnStart(this);
    // 省略代碼
}
複製代碼

在mInstrumentation.callActivityOnStart(this)方法裏面就會顯式調用Activtiy的onStart()方法!

到這裏咱們也能夠基本解決第二個問題:Activity的生命週期方法是經過Instrumentation類調用callActivityOnXXX方法最終調用Activity的onCreate等方法,調用時機爲ActivityThread#performLaunchActivitiy()方法中。

那麼還有一個問題,咱們知道啓動一個Activity,所經歷的生命週期爲onCreate() --> onStart() --> onResume() 那麼onResume()方法在哪裏調用的呢? 咱們回到前面的ActivityThread#handleLaunchActivity():

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    // 省略代碼
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        // !!!
        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    // 省略代碼
}
複製代碼

在咱們調用performLaunchActivity以後返回新生成的Activity實例以後,接下來就會調用handleResumeActivity()方法 ActivityThread#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
    // !!!
    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 = ActivityManagerNative.getDefault().willActivityBeVisible(a.getActivityToken());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            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;
                // Normally the ViewRoot sets up callbacks with the Activity
                // in addView->ViewRootImpl#setView. If we are instead reusing
                // the decor view we have to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient && !a.mWindowAdded) {
                a.mWindowAdded = true;
                wm.addView(decor, l);
            }
            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
        } 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, REPORT_TO_ACTIVITY);
                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) {
                    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 {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    } else {
        // If an exception was thrown when trying to resume, then
        // just end this activity.
        try {
            ActivityManagerNative.getDefault().
                      finishActivity(token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex)
        throw ex.rethrowFromSystemServer();
    }
}
複製代碼

這裏會調用: ActivityThread#performResumeActivity()   --> Activity#performResume()     --> Instrumentation#callActivityOnResume()       --> Activity#onResume() 另外,觀察執行handleResumeActivity()以後的代碼,會發現程序會開始獲取DecorView,執行addView()方法,裏面最終會調用到ViewRootImpl#performTraversals(),即開始繪製view界面! 這裏咱們就解決了第三個問題:界面的繪製是在執行Activity#onResume()以後!

3、關於第四個問題

那麼咱們還差第四個問題沒有解決!爲何咱們這個流程都沒有涉及到調用main方法呢,是由於在一開始,咱們分析的狀況是在已有的App進程中啓動一個新的Activity,而經過咱們上文的分析,咱們知道ActivityThread類纔是應用的主線程類,一個app應用進程有且只有一個ActivityThread類,也就是咱們一直說的應用程序主線程(UI線程)。因此,在分析源碼時,咱們已經假設ActivityThread類已經存在實例,因此不會再調用main方法。

那麼什麼狀況下會調用到main方法呢,其實咱們每次在手機的桌面點擊一個應用圖標打開應用時,實際上是通由Launcher啓動起來的。

(1)關於Launcher Launcher自己也是一個應用程序,其它的應用程序安裝後,就會Launcher的界面上出現一個相應的圖標,點擊這個圖標時,Launcher就會對應的應用程序啓動起來。Launcher其實也是Activity的一個子類。

public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher { 
    ...
}
複製代碼

因此本質上也是調用了startActivity()方法啓動一個新的Activity! 根據上述的流程,一直到ActivityStackSupervisor#startSpecificActivityLocked()這裏,代碼的調用流程就會開始發生變化! ActivityStackSupervisor#startSpecificActivityLocked()

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
    r.task.stack.setLaunchTime(r);
    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) {
                // Don't add this if it is a platform component that is marked
                // to run in multiple processes, because this is actually
                // part of the framework so doesn't make sense to track as a
                // separate apk in the process.
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats);
            }
            // !!!
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e);
        }
        // If a dead object exception was thrown -- fall through to
        // restart the application.
    }
    mService.startProcessLocked(r.processName, r.info.applicationInfo, 
            true, 0, "activity", r.intent.getComponent(), false, false, true);
}
複製代碼

上文說過。這裏會判斷進程是否存在,而此次,app爲空,因此會跳出if判斷,直接到下面的mService.startProcessLocked()方法,這裏的mService爲ActivityManagerService類的一個實例! startProcessLocked()經過幾回重載函數的調用,最終調用到這裏:

private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    // 省略代碼
    // Start the process. It will either succeed and return a result containing
    // the PID of the new process, or else throw a RuntimeException.
    boolean isActivityProcess = (entryPoint == null);
    if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName);
    checkTime(startTime, "startProcess: asking zygote to start proc");
    // !!!
    Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, 
                uid, gids, debugFlags, mountExternal, 
                app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, 
                app.info.dataDir, entryPointArgs);
    // 省略代碼
}
複製代碼

(2) Process#start()   --> Process#startViaZygote()

private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx {
        ArrayList < String > argsForZygote = new ArrayList < String > ();
    // --runtime-args, --setuid=, --setgid=,
    // and --setgroups= must go first
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
        argsForZygote.add("--enable-jni-logging");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
        argsForZygote.add("--enable-safemode");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
        argsForZygote.add("--enable-debugger");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
        argsForZygote.add("--enable-checkjni");
    }
    if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
        argsForZygote.add("--generate-debug-info");
    }
    if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) {
        argsForZygote.add("--always-jit");
    }
    if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {
        argsForZygote.add("--native-debuggable");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
        argsForZygote.add("--enable-assert");
    }
    if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
        argsForZygote.add("--mount-external-default");
    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
        argsForZygote.add("--mount-external-read");
    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
        argsForZygote.add("--mount-external-write");
    }
    argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
    //TODO optionally enable debuger
    //argsForZygote.add("--enable-debugger");
    // --setgroups is a comma-separated list
    if (gids != null && gids.length > 0) {
        StringBuilder sb = new StringBuilder();
        sb.append("--setgroups=");
        int sz = gids.length;
        for (int i = 0; i < sz; i++) {
            if (i != 0) {
                sb.append(',');
            }
            sb.append(gids[i]);
        }
        argsForZygote.add(sb.toString());
    }
    if (niceName != null) {
        argsForZygote.add("--nice-name=" + niceName);
    }
    if (seInfo != null) {
        argsForZygote.add("--seinfo=" + seInfo);
    }
    if (instructionSet != null) {
        argsForZygote.add("--instruction-set=" + instructionSet);
    }
    if (appDataDir != null) {
        argsForZygote.add("--app-data-dir=" + appDataDir);
    }
    argsForZygote.add(processClass);
    if (extraArgs != null) {
        for (String arg: extraArgs) {
            argsForZygote.add(arg);
        }
    }
    return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
複製代碼

上面方法中設置一些參數以後,調用最後的zygoteSendArgsAndGetResult(),方法的做用是向Zygote發送建立進程請求,內部與Zygote進行Socket通訊。具體代碼邏輯在ZygoteInit#runSelectLoop():

(3)ZygoteInit#runSelectLoop():

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList < FileDescriptor > fds = new ArrayList < FileDescriptor > ();
    ArrayList < ZygoteConnection > peers = new ArrayList < ZygoteConnection > ();
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);
    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}
複製代碼

上面方法當中,經過acceptCommandPeer()方法建立一個新的ZygoteConnection,調用runOnce()方法處理請求。 ZygoteConnection#runOnce():

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;
    try {
        // 讀取參數
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        Log.w(TAG, "IOException on command socket " + ex.getMessage());
        closeSocket();
        return true;
    }
    if (args == null) {
        // EOF reached.
        closeSocket();
        return true;
    }
    /** the stderr of the most recent request, if avail */
    PrintStream newStderr = null;
    if (descriptors != null && descriptors.length >= 3) {
        newStderr = new PrintStream(new FileOutputStream(descriptors[2]));
    }
    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;
    try {
        // 省略代碼
        // !!!
        pid = Zygote.forkAndSpecialize(parsedArgs.uid,
                      parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlags, 
                      rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName,
                      fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir);
    } catch (ErrnoException ex) {
        logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (IllegalArgumentException ex) {
        logAndPrintError(newStderr, "Invalid zygote arguments", ex);
    } catch (ZygoteSecurityException ex) {
        logAndPrintError(newStderr, "Zygote security policy prevents request: ", ex);
    }
    try {
        if (pid == 0) {
            // in child
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            // !!!
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            // should never get here, the child is expected to either
            // throw ZygoteInit.MethodAndArgsCaller or exec().
            return true;
        } else {
            // in parent...pid of < 0 means failure
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}
複製代碼

這裏會調用Zygote.forkAndSpecialize()方法生成一個新的進程,若是生成成功,則pid的值爲0,而後調用handleChildProc()方法:

private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {
    /** * By the time we get here, the native code has closed the two actual Zygote * socket connections, and substituted /dev/null in their place. The LocalSocket * objects still need to be closed properly. */

    closeSocket();
    ZygoteInit.closeServerSocket();

    if (descriptors != null) {
        try {
            Os.dup2(descriptors[0], STDIN_FILENO);
            Os.dup2(descriptors[1], STDOUT_FILENO);
            Os.dup2(descriptors[2], STDERR_FILENO);

            for (FileDescriptor fd: descriptors) {
                IoUtils.closeQuietly(fd);
            }
            newStderr = System.err;
        } catch (ErrnoException ex) {
            Log.e(TAG, "Error reopening stdio", ex);
        }
    }

    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }

    // End of the postFork event.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.remainingArgs);
    } else {
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs, null /* classLoader */);
    }
}
複製代碼

這裏會根據invokeWith參數決定使用哪一種執行方式,咱們只要知道SystemServer和apk都是經過RuntimeInit類生成的便可。

(4)RuntimeInit#zygoteInit()

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
    if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
    redirectLogStreams();

    commonInit();
    nativeZygoteInit();
    applicationInit(targetSdkVersion, argv, classLoader);
}
複製代碼

最後會調用applicationInit()方法:

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
    // 省略代碼

    // Remaining arguments are passed to the start class's static main
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
複製代碼

最關鍵的就是invokeStaticMain()方法:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;

    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
    }

    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
                    "Missing static main on " + className, ex);
    } catch (SecurityException ex) {
        throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
    }

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                    "Main method is not public and static on " + className);
    }

    /* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
複製代碼

上述方法中,經過反射的方式獲取main方法,最後拋出一個MethodAndArgsCaller,它繼承於Exception,同時他也是實現了Runnable接口。看 throw new ZygoteInit.MethodAndArgsCaller()的代碼註釋咱們能夠知道,它會在ZygoteInit.main()方法中被捕獲,執行run方法。

public static class MethodAndArgsCaller extends Exception implements Runnable {
    /** method to call */
    private final Method mMethod;

    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }

    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InvocationTargetException ex) {
            Throwable cause = ex.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            }
            throw new RuntimeException(ex);
        }
    }
}
複製代碼

咱們能夠知道,最終它將會調用ActivityThread類的main方法! 因此,咱們解決了第四個問題,ActivityThread的main方法是在生成一個新的app進程過程當中調用的,具體是經過與Zygote通訊,以後經過RuntimeInit類採用反射的方式調用ActivityThread#main()方法,即生成app中的主線程(UI線程)!

這篇文章會同步到個人我的日誌,若有問題,請你們踊躍提出,謝謝你們!

相關文章
相關標籤/搜索