原始碼探探之StartActivity(一)

94me發表於2017-10-18

原始碼基於API 26

startActivity()上車

@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}複製程式碼

沒什麼好說的

//啟動一個activity不需要返回值
//如果context之外呼叫startActivity(),需要給intent新增{@link Intent#FLAG_ACTIVITY_NEW_TASK}
//@param options 附加的選項指示如果啟動activity
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        //可重寫該方法相容應用需求
        startActivityForResult(intent, -1);
    }
}複製程式碼

可重寫該方法,參考FragmentActivity

//If requestCode >= 0, this code will be returned in onActivityResult() when the activity exits.
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}複製程式碼

最終執行該方法

//啟動一個activity在finish()會返回一個結果在onActivityResult()中
//如果在onCreate()/onResume()方法中呼叫該方法,window不顯示介面直到該方法返回結果
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    //父activity一般為空
    if (mParent == null) {
        //通過ActivityOptions幫助類生成一個bundle,指示該如何啟動該activity
        options = transferSpringboardActivityOptions(options);
        //Instrumentation基類啟動Activity
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        //返回結果
        if (ar != null) {
            //最終會執行Activity的onActivityResult()
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            //當接收到返回的結果了啟動的activity才會顯示
            mStartedActivity = true;
        }
        //取消輸入並開始activity退出動畫
        cancelInputsAndStartExitTransition(options);
    } else {
        //不考慮mParent不為null的情況,遠古級方法,不採用了
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}複製程式碼

執行Instrumentation的execStartActivity(),Instrumentation起著監控系統和應用的作用

//target:源activity
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    //獲取當前內容索引,不重寫onProvideReferrer()返回null
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        //不為null新增至intent
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    //activity監視器
    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並離開當前程式
        intent.prepareToLeaveProcess(who);
        //本地activityManager啟動activity
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        //檢查啟動activity返回結果,丟擲異常
        checkStartActivityResult(result, intent);
        //跨程式異常
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}複製程式碼

ActivityManagerNative.getDefault()獲取IActivityManager介面,呼叫startActivity()方法。
事實上是ServiceManager.getService("activity"), 即獲取ActivityManagerService(AMS)並通過Binder遠端呼叫ActivityManagerService類的startActivity()方法。

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        //獲取activityService
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        //返回service代理物件
        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;
    }
    //通過binder獲取AMS
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    //代理obj其實就是AMS
    return new ActivityManagerProxy(obj);
}複製程式碼

IAvityManager對所有執行著的Activity互動提供了介面,ActivityMangerNative實現了IActivityManager介面,IActivityManger的大多數功能都是呼叫了ActivityManagerNative類介面來完成的,而AMS繼承了ActivityMangerNative。
ActivityMangerNative作為IActivityManger和AMS的中間類,解耦了兩者間的依賴,所有對AMS的訪問都轉換成了對ActivityMangerNative的代理類ActivityMangerProxy的訪問。

從這裡的getDefault().startActivity()開始從本應用通過binder跨程式呼叫AMS的方法

@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());
}
@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);
}複製程式碼

ActivityStarter類負責處理啟動activity之前的準備工作,包括Activity的Intent和Flags的邏輯, 還有管理Stack和TaskRecord.
ActivityStarter類的呼叫流程:

  • ActivityStarter#startActivityMayWait(根據Intent獲取Activity的啟動資訊(ResolveInfo和ActivityInfo)
  • ActivityStarter#startActivityLocked(建立ActivityRecord, 含有Activity的核心資訊)
  • ActivityStarter#startActivityUnchecked(根據啟動的Flag資訊, 設定TaskRecord)

接著執行ActivityStackSupervisor類的resumeFocusedStackTopActivityLocked()方法

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || r.state != RESUMED) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }
    return false;
}複製程式碼

ActivityStackSupervisor類與ActivityStack類配合使用. ActivityStackSupervisor負責管理Task和Stack, 而ActivityStack負責管理在Stack和Task中的Activity

ActivityStackSupervisor類與ActivityStack類的呼叫流程:

  • ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
  • ActivityStack#resumeTopActivityUncheckedLocked
  • ActivityStack#resumeTopActivityInnerLocked(根據ActivityRecord和ActivityOptions完成Activity的切換, 移至棧頂)
  • ActivityStackSupervisor#startSpecificActivityLocked
  • ActivityStackSupervisor#realStartActivityLocked(真正啟動activity)

     final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
             boolean andResume, boolean checkConfig) throws RemoteException {
         ...
         app.forceProcessStateUpTo(mService.mTopProcessState);
         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);
         ...
     }複製程式碼

    最後由ActivityThread中的ApplicationThread呼叫scheduleLaunchActivity完成Activity的真正啟動。
    這裡的thread是IApplicationThread介面,該介面繼承了IInterface介面,實現方法asBinder()方法作為binder通訊。

    這裡通過binder跨程式由系統程式呼叫應用程式啟動activity

相關文章