1. 程式人生 > >Activity啟動流程筆記(一)

Activity啟動流程筆記(一)

從startActivity開始說起:

public void startActivity(Intent intent, 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); } }

進入startActivityForResult看看:

/**
     * Launch an activity for which you would like a result when it finished.
     * When this activity exits, your
     * onActivityResult() method will be called with the given requestCode. 
     * Using a negative requestCode is
the same as calling * {@link #startActivity} (the activity is not launched as a sub-activity). * * <p>Note that this method should only be used with Intent protocols * that are defined to return a result. In other protocols (such as * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
* not get the result when you expect. For example, if the activity you * are launching uses the singleTask launch mode, it will not run in your * task and thus you will immediately receive a cancel result. * * <p>As a special case, if you call startActivityForResult() with a requestCode * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your * activity, then your window will not be displayed until a result is * returned back from the started activity. This is to avoid visible * flickering when redirecting to another activity. * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode, Bundle options) { if (mParent == null) {/*1*/ 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) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } final View decor = mWindow != null ? mWindow.peekDecorView() : null; if (decor != null) { decor.cancelPendingInputEvents(); } // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }

mParent 表示Activity的父Activity,在用ActivityGroup的時候會出現這種情況,現在幾乎不會用到,所以直接看mParent != null這種情況。在進入mInstrumentation的execStartActivity方法之前先看看引數:mMainThread.getApplicationThread()返回一個AplicationThread物件,這個物件其實是一個Binder,用於AMS與Activity通訊。mMainThread是ActivityThread,ActivityThread是一個app的入口,mToken是一個AppWindowToken型別的物件,專門標識Activity型別的Window。

來看下Instrumentation的execStartActivity:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

主要看這段程式碼:ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
這個方法引數有點多,先看ActivityManagerNative.getDefault這個函式,他其實返回了一個AMS在客戶端的代理,即一個ActivityManagerProxy

static public IActivityManager getDefault() {
        return gDefault.get();
    }

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

可以得知之前的startActivity呼叫的是ActivityManagerProxy中的方法
看到ActivityManagerProxy與ActivityManagerService都繼承自ActivityManagerNative,可以想到AIDL,啟動Activity需要通過AIDL跨程序與AMS互動,所以在ActivityManagerProxy的startActivity會將AIDL需要的引數進行快程序傳遞

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, 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);
        data.writeString(profileFile);
        if (profileFd != null) {
            data.writeInt(1);
            profileFd.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;
    }

可以看到IApplicaiotnThread物件也被包裝成一個binder傳遞到AMS端,傳遞的實際是個ApplicationThreadProxy型別,用於AMS向ActivityThread通訊,控制Activity。
至此,就進入到AMS中進行後續的啟動。