Android開發藝術探索 - 第9章 四大組件的工作過程

1.Activity啓動過程 ref

從Activity的startActivity方法開始。startActivity的多個重載方法,最終都會調用startActivityForResult方法。mParent代表的是ActivityGroup,API 13之前用於在一個界面中嵌入多個Activity,之後被Fragment替代,所以這裏一般爲null。該方法中主要調用了Instrumentation#execStartActivity,其中參數mMainThread.getApplicationThread()得到的是ActivityThread的子類ApplicationThread對象,這兩個類在Activity的啓動過程中發揮了重要的作用:

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());
        }

execStartActivity的關鍵代碼,即ActivityManager.getService().startActivity。從API 26開始引入了新的ActicityManager類,替代之前舊的實現ActivityManagerNative,不過最終得到都是一個IActivityManager的單例對象,其具體實現爲ActivityManagerService(AMS)。緊隨其後的方法checkStartActivityResult,則處理了常見的找不到Intent時拋出異常的情況:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    ...

    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);
public static void checkStartActivityResult(int res, Object intent) {
    if (!ActivityManager.isStartResultFatalError(res)) {
        return;
    }

    switch (res) {
        case ActivityManager.START_INTENT_NOT_RESOLVED:
        case ActivityManager.START_CLASS_NOT_FOUND:
            if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                throw new ActivityNotFoundException(
                        "Unable to find explicit activity class "
                        + ((Intent)intent).getComponent().toShortString()
                        + "; have you declared this activity in your AndroidManifest.xml?");
            throw new ActivityNotFoundException(
                    "No Activity found to handle " + intent);

然後來到AMS#startActivity方法,最終通過startActivityAsUser方法,調用了ActivityStartController#obtainsStarter得到一個ActivityStarter對象,執行了其execute方法。setMayWait設置了其wait標誌位爲true:

    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,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivity");

        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

轉到ActivityStarter#execute方法,調用了startActivityMayWait方法(上面提到wait被置爲true),經過一翻流轉:ActivityStarter->ActivityStackSupervisor->ActivityStack->ActivityStackSupervisor,最終調用到ActivityStackSupervisor#realStartActivityLocked方法,關鍵代碼如下。與之前不同,API 28開始,通過事務的方式啓動Activity:

// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
        r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global
        // and override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
        profilerInfo));
...
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);

ClientLifecycleManager#scheduleTransaction,在創建ClientTransaction的時候,IApplicationThread接口的Binder對象就從Parcel中讀取出來,並指向了mClient。這裏調用了transaction的schedule方法,實際就是調用了Binder對象的scheduleTransaction方法:

void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    transaction.schedule();
    if (!(client instanceof Binder)) {
        // If client is not an instance of Binder - it's a remote call and at this point it is
        // safe to recycle the object. All objects used for local calls will be recycled after
        // the transaction is executed on client in ActivityThread.
        transaction.recycle();
    }
}
// ClientTransaction#schedule
public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

而這個Binder對象遠程Binder實體,即是在最開始startActivityForResult方法中,mMainThread.getApplicationThread()得到的ActivityThread$ApplicationThread實例。其scheduleTransaction方法最終調用到ActivityThread父類的scheduleTransaction方法。舊版本中,沒有事務的概念,而是直接調用了該方法:

// ActivityThread$ApplicationThread#scheduleTransaction    
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}

而其scheduleTransaction的實現則非常簡單,直接發送了一個Message交由Handler處理:

// ClientTransactionHandler#scheduleTransaction
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

Handler中執行了mTransactionExecutor.execute(transaction);

case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);
    if (isSystem()) {
        // Client transactions inside system process are recycled on the client side
        // instead of ClientLifecycleManager to avoid being cleared before this
        // message is handled.
        transaction.recycle();
    }
    // TODO(lifecycler): Recycle locally scheduled transactions.
    break;

在TransactionExecutor的excute中,調用executeCallbacks執行具體的事務ClientTransactionItem:

public void execute(ClientTransaction transaction) {
    final IBinder token = transaction.getActivityToken();
    log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

    executeCallbacks(transaction);

    executeLifecycleState(transaction);
    mPendingActions.clear();
    log("End resolving transaction");
}

@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    if (callbacks == null) {
        // No callbacks to execute, return early.
        return;
    }
    log("Resolving callbacks");

    final IBinder token = transaction.getActivityToken();
    ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

    ...
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        ...

        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);

而這裏的ClientTransactionItem的實現類,實際爲創建事務時,傳入的LaunchActivityItem對象,其execute方法調用了client.handleLaunchActivity(r, pendingActions, null /* customIntent */);,這裏的client就是ActivityThread:

@Override
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

在ActivityThread的ActivityThread方法中,最終調用到了performLaunchActivity方法:

@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    ...

    final Activity a = performLaunchActivity(r, customIntent);

進入performLaunchActivity方法,開始創建Activity:

  • 從ActivityClientRecord中獲取待啓動的Activity的組件信息:
    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,通過Instrumentation#newActivity方法使用ClassLoader創建Activity對象:
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
    java.lang.ClassLoader cl = appContext.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);
    }
  • 通過LoadedApk#makeApplication方法嘗試創建Application對象。如果Application已經創建過了,則不會再次創建,所以一個應用只有一個Application。而創建過程同Activity也是通過Instrumentation#newApplication方法使用ClassLoader創建,創建完成後,通過callApplicationOnCreate回調Application#onCreate方法:
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
            ...

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
  • 通過Activity#attach方法來完成重要數據的初始化,與ContextImpl的關聯,以及Window創建和與Window的關聯。
appContext.setOuterContext(activity);
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);
  • 調用Activity#onCreate方法
    通過mInstrumentation.callActivityOnCreate(activity, r.state);回調Activity#onCreate。至此,Activity創建完畢。

2.Service

  1. 啓動過程
    Activity#startService->ContextWrapper#startService,這裏的mBase,即是創建Activity時,關聯的ContextImpl對象。ContextWrapper的實現大部分由ContextImpl完成,典型的橋接模式:
@Override
public ComponentName startService(Intent service) {
    return mBase.startService(service);
}

ContextImpl#startService->startServiceCommon,同Activity,同樣會通過AMS去執行startService操作:
```
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
```

AMS#startService中調用mService的startServiceLocked方法,這個mService的類型是ActiveService,他的作用是輔助AMS進行service的啓動/綁定/停止:

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
        ...
        try {
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);

startServiceLocked->startServiceInnerLocked,傳遞的ServiceRecord描述了一個service記錄,其一直貫穿整個service的啓動過程。然後調用bringUpServiceLocked:

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    ServiceState stracker = r.getTracker();
    if (stracker != null) {
        stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
    }
    r.callStart = false;
    synchronized (r.stats.getBatteryStats()) {
        r.stats.startRunningLocked();
    }
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);

bringUpServiceLocked->realStartServiceLocked,其中主要關注兩個調用:首先同Activity,遠程調用了ApplicationThread#scheduleCreateService創建service,回調onCreate方法;然後通過sendServiceArgsLocked方法來調用其他方法,如onStartCommand方法:

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
        ...

    try {
        ...
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
    ...

    sendServiceArgsLocked(r, execInFg, true);

ApplicationThread#scheduleCreateService,同Activity,也是發送Message給Handler處理:

public final void scheduleCreateService(IBinder token,
        ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    CreateServiceData s = new CreateServiceData();
    s.token = token;
    s.info = info;
    s.compatInfo = compatInfo;

    sendMessage(H.CREATE_SERVICE, s);
}

Handler異步回調handleCreateService創建service:

  • 通過ClassLoader創建service:
    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = packageInfo.getAppFactory()
                .instantiateService(cl, data.info.name, data.intent);
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                + ": " + e.toString(), e);
        }
    }
    
  • 創建ContextImpl,並通過service的attach方法進行關聯;視情況創建Application實例,同Activity;回調service的onCreate方法;最後,將service實例存儲到ArrayMap中:
    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
    context.setOuterContext(service);
    
    Application app = packageInfo.makeApplication(false, mInstrumentation);
    service.attach(context, this, data.info.name, data.token, app,
            ActivityManager.getService());
    service.onCreate();
    mServices.put(data.token, service);
    
    final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
    

service創建完畢,之後會被遠程調用handleServiceArgs方法,進而回調onStartCommand。
2. 綁定過程
Activity#bindService->ContextWrapper#bindService->ContextWrapper#bindServiceCommon,首先,通過LoadedApk#getServiceDispatcher方法,根據ServiceConnection得到IServiceConnection接口的Binder對象,因爲bind操作可能是跨進程,所以要使用Binder支持IPC。然後調用AMS的遠程bindService方法:

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
    // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
    IServiceConnection sd;
    ...
    if (mPackageInfo != null) {
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
    ...
    try {
    ...
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());

獲得IServiceConnection接口Binder對象的過程:每個Context對應一個map,存儲了<ServiceConnection,LoadedApk.ServiceDispatcher>的map,通過這個ServiceDispatcher的getIServiceConnection方法,可以得到其內部類InnerConnection的實例,該類實現了IServiceConnection接口:

public final IServiceConnection getServiceDispatcher(ServiceConnection c,
        Context context, Handler handler, int flags) {
    synchronized (mServices) {
        LoadedApk.ServiceDispatcher sd = null;
        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
        if (map != null) {
            if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
            sd = map.get(c);
        }
        if (sd == null) {
            sd = new ServiceDispatcher(c, context, handler, flags);
            if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
            if (map == null) {
                map = new ArrayMap<>();
                mServices.put(context, map);
            }
            map.put(c, sd);
        } else {
            sd.validate(context, handler);
        }
        return sd.getIServiceConnection();
    }
}

AMS#bindService->ActiveServices#bindServiceLocked->bringUpServiceLocked->realStartServiceLocked,之後的流程同創建Service,會通過ApplicationThread來完成service創建以及onCreate方法的回調。另外,realStartServiceLocked方法中,會調用requestServiceBindingsLocked(r, execInFg)方法,根據record執行app.thread.scheduleBindService來進行onBind回調:

private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
        throws TransactionTooLargeException {
    for (int i=r.bindings.size()-1; i>=0; i--) {
        IntentBindRecord ibr = r.bindings.valueAt(i);
        if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
            break;
        }
    }
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
        boolean execInFg, boolean rebind) throws TransactionTooLargeException {
    ...
    if ((!i.requested || rebind) && i.apps.size() > 0) {
        try {
            bumpServiceExecutingLocked(r, execInFg, "bind");
            r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                    r.app.repProcState);

在ActivityThread中,同樣是通過Handler,最終執行到其handleBindService方法。回調service的onBind方法,onBind返回一個Binder對象,通過AMS#publishService將其傳遞給client,client的onServiceConnected接收到,bind操作完成:

// ApplicationThread#scheduleBindService
public final void scheduleBindService(IBinder token, Intent intent,
        boolean rebind, int processState) {
    ...
    sendMessage(H.BIND_SERVICE, s);
}
private void handleBindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    if (DEBUG_SERVICE)
        Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
    if (s != null) {
        try {
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            try {
                if (!data.rebind) {
                    IBinder binder = s.onBind(data.intent);
                    ActivityManager.getService().publishService(
                            data.token, data.intent, binder);
                } else {
                    s.onRebind(data.intent);
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }

client接收Binder的具體過程:AMS#publishService->ActiveServices#publishServiceLocked,其關鍵代碼c.conn.connected(r.name, service, false),c.conn即IServiceConnection接口,對應之前的ServiceDispatcher.InnerConnection類型:

public void connected(ComponentName name, IBinder service, boolean dead)
        throws RemoteException {
    LoadedApk.ServiceDispatcher sd = mDispatcher.get();
    if (sd != null) {
        sd.connected(name, service, dead);
    }
}

進而調用ServiceDispatcher#connected。這裏的mActivityThread的類型爲Handler,他是在創建ServiceDispatcher時,傳遞進來的ActivityThread的Handler實例。所以最終會通過該Handler在主線程執行RunConnection:

        public void connected(ComponentName name, IBinder service, boolean dead) {
            if (mActivityThread != null) {
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }

RunConnection#run則執行了ServiceDispatcher#doConnected,client的onServiceConnected被調用:

public void doConnected(ComponentName name, IBinder service, boolean dead) {
    ...
    // If there is a new viable service, it is now connected.
    if (service != null) {
        mConnection.onServiceConnected(name, service);
    } 

3.BroadcastReceiver

  1. 註冊過程
    靜態註冊,同其他三大組件,在應用安裝時通過PMS(PackageManagerService)解析並註冊。
    動態註冊過程如下。
    ContextWrapper#registerReceiver->ContextImpl#registerReceiver->registerReceiverInternal。與bind service類似,也是先得到一個供遠程AMS調用的Binder實例,類型爲IIntentReceiver,實現類爲ReceiverDispatcher.InnerReceiver;之後調用AMS#registerReceiver方法:
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
    IIntentReceiver rd = null;
    ...
            rd = new LoadedApk.ReceiverDispatcher(
                    receiver, context, scheduler, null, true).getIIntentReceiver();
        }
    }
    try {
        final Intent intent = ActivityManager.getService().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                broadcastPermission, userId, flags);

AMS#registerReceiver關鍵代碼,將InnerReceiver遠程Binder和IntentFilter對象存儲起來:

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
        int flags) {
        ...
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        ...
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId, instantApp, visibleToInstantApps);
        if (rl.containsFilter(filter)) {
            Slog.w(TAG, "Receiver with filter " + filter
                    + " already registered for pid " + rl.pid
                    + ", callerPackage is " + callerPackage);
        } else {
            rl.add(bf);
            if (!bf.debugCheck()) {
                Slog.w(TAG, "==> For Dynamic broadcast");
            }
            mReceiverResolver.addFilter(bf);
  1. 發送接收過程
    從廣播的發送開始。
    ContextWrapper#sendBroadcast->ContextImpl#sendBroadcast->AMS#broadcastIntent->AMS#broadcastIntentLocked。首先,爲其Intent中添加Intent.FLAG_EXCLUDE_STOPPED_PACKAGES,從Android 5.0起,默認不會向已經停止的app發送廣播。如果希望向停止的app發送廣播,添加Intent.FLAG_INCLUDE_STOPPED_PACKAGES即可,當兩個flag同時存在,以include爲準:
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

之後,broadcastIntentLocked的主要工作就是,根據intent-filter查找出匹配的receiver,終將滿足的receiver添加到BroadcastRecord中,接着執行scheduleBroadcastsLocked方法發送廣播:

int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
    ...
    final BroadcastQueue queue = broadcastQueueForIntent(intent);
    BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
            callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
            requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
            resultCode, resultData, resultExtras, ordered, sticky, false, userId);
    ...
    if (!replaced) {
        queue.enqueueParallelBroadcastLocked(r);
        queue.scheduleBroadcastsLocked();
    }
    registeredReceivers = null;
    NR = 0;
}
...
if ((receivers != null && receivers.size() > 0)
        || resultTo != null) {
    BroadcastQueue queue = broadcastQueueForIntent(intent);
    BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
            callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
            requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
            resultData, resultExtras, ordered, sticky, false, userId);
    ...
    } else {
        queue.enqueueOrderedBroadcastLocked(r);
        queue.scheduleBroadcastsLocked();
    }

BroadcastQueue#scheduleBroadcastsLocked只是發出一個message:

    public void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                + mQueueName + "]: current="
                + mBroadcastsScheduled);

        if (mBroadcastsScheduled) {
            return;
        }
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

之後,Handler調用processNextBroadcast->processNextBroadcastLocked。以無序廣播爲例,取出BroadcastRecord,遍歷其中的receiver,調用deliverToRegisteredReceiverLocked方法向target發出廣播:

// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
    r = mParallelBroadcasts.remove(0);
    ...
    for (int i=0; i<N; i++) {
        Object target = r.receivers.get(i);
        if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                "Delivering non-ordered on [" + mQueueName + "] to registered "
                + target + ": " + r);
        deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);

deliverToRegisteredReceiverLocked->performReceiveLocked,最終調用了app.thread.scheduleRegisteredReceiver,回到了ApplicationThread:

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
        Intent intent, int resultCode, String data, Bundle extras,
        boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
    // Send the intent to the receiver asynchronously using one-way binder calls.
    if (app != null) {
        if (app.thread != null) {
            // If we have an app thread, do the call through that so it is
            // correctly ordered with other one-way calls.
            try {
                app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                        data, extras, ordered, sticky, sendingUser, app.repProcState);

ApplicationThread#scheduleRegisteredReceiver->IIntentReceiver.performReceive,IIntentReceiver即爲註冊receiver時,創建的Binder對象實例,類型爲ReceiverDispatcher.InnerReceiver:

        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            updateProcessState(processState, false);
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

InnerReceiver#performReceive->ReceiverDispatcher#performReceive,該方法中,通過
創建一個Runnable,將調用onReceive的操作,交給mActivityThread即Handler去執行,該Handler就是ActivityThread中的H:

public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final Args args = new Args(intent, resultCode, data, extras, ordered,
            sticky, sendingUser);
    ...
    if (intent == null || !mActivityThread.post(args.getRunnable())) {

最終,onReceive在主線程中被調用:

try {
    ClassLoader cl = mReceiver.getClass().getClassLoader();
    intent.setExtrasClassLoader(cl);
    intent.prepareToEnterProcess();
    setExtrasClassLoader(cl);
    receiver.setPendingResult(this);
    receiver.onReceive(mContext, intent);

4.ContentProvider


應用啓動流程:

  • VM調用ActivityThread的main方法。
  • main方法中,會創建ActivityThread的實例,然後調用其attach方法;同時會創建主線程的消息隊列。
  • attch方法中,會調用AMS的遠程方法attachApplication,將其ApplicationThread傳遞給AMS。ApplicationThread是個Binder對象,用於ActivityThread和AMS的通信。
  • 在AMS的attachApplication方法中,會遠程調用ApplicationThread的bindApplication方法,ApplicationThread轉而交由ActivityThread的Handler處理,具體方法爲handleBindApplication。
  • 在handleBindApplication方法中,會創建Application對象,並加載ContentProvider。加載過程發生在回調Application的onCreate方法之前。

ContentProvider可以通過android:multiProcess來爲其指定多實例,在每個調用者的進程中,都存在一個CopntentProvider實例。不過大部分的使用場景,ContentProvider爲單實例。
訪問ContentProvider使用的ContentResolver是個抽象類,getContentResolver得到的實例實際爲ContextImpl.ApplicationContentResolver。當通過其四個方法訪問ContentProvider時,其所在進程未啓動,則會觸發其創建,並伴隨着ContentProvider的創建。這裏以query爲例。

ContentResolver#query首先調用了acquireUnstableProvider方法,來獲取一個IContentProvider實例。然後調用了子類的acquireUnstableProvider方法,這裏的mMainThread即是ActivityThread:

@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
    return mMainThread.acquireProvider(c,
            ContentProvider.getAuthorityWithoutUserId(auth),
            resolveUserIdFromAuthority(auth), false);
}

ActivityThread#acquireProvider,首先會判斷目標provider是否存在,如果存在直接返回;如果不存在則通過AMS#getContentProvider方法去創建他,最後通過installProvider修改引用計數:

    public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        if (provider != null) {
            return provider;
        }
        ...
        try {
            synchronized (getGetProviderLock(auth, userId)) {
                holder = ActivityManager.getService().getContentProvider(
                        getApplicationThread(), auth, userId, stable);
        ...
        // Install provider will increment the reference count for us, and break
        // any ties in the race.
        holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;
    }

AMS#getContentProvider->AMS#getContentProviderImpl->startProcessLocked->startProcess,首先創建目標進程。具體爲調用了Process.start方法:

private ProcessStartResult startProcess(String hostingType, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
        String seInfo, String requiredAbi, String instructionSet, String invokeWith,
        long startTime) {
        ...
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, invokeWith,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});

新進程啓動後,其入口方法爲ActivityThread#main:

    public static void main(String[] args) {
        ...

        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

如前述,Activity#attach->AMS#attachApplication->AMS#attachApplicationImpl->ApplicationThread#bindApplication,然後交由ActivityThread的Handler處理,具體在handleBindApplication方法:
首先,創建ContextImpl和Instrumentation:

final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

try {
    final ClassLoader cl = instrContext.getClassLoader();
    mInstrumentation = (Instrumentation)
        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
    throw new RuntimeException(
        "Unable to instantiate instrumentation "
        + data.instrumentationName + ": " + e.toString(), e);
}

final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
        data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

創建Application:

Application app;
...
try {
    // If the app is being launched for full backup or restore, bring it up in
    // a restricted environment with the base application class.
    app = data.info.makeApplication(data.restrictedBackupMode, null);
    ...
    mInitialApplication = app;

創建ContentProvider,並調用其onCreate方法。

  • installContentProviders方法中,遍歷當前進程的ProviderInfo列表,一一調用其installProvider方法來啓動他們。然後將ContentProvider發佈到AMS當中,AMS會把其存儲在ProviderMap中,下次調用便可直接獲得provider實例:
installContentProviders(app, data.providers);
private void installContentProviders(
        Context context, List<ProviderInfo> providers) {
    final ArrayList<ContentProviderHolder> results = new ArrayList<>();

    for (ProviderInfo cpi : providers) {
        if (DEBUG_PROVIDER) {
            StringBuilder buf = new StringBuilder(128);
            buf.append("Pub ");
            buf.append(cpi.authority);
            buf.append(": ");
            buf.append(cpi.name);
            Log.i(TAG, buf.toString());
        }
        ContentProviderHolder cph = installProvider(context, null, cpi,
                false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
        if (cph != null) {
            cph.noReleaseNeeded = true;
            results.add(cph);
        }
    }

    try {
        ActivityManager.getService().publishContentProviders(
            getApplicationThread(), results);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}
  • provider的具體創建過程在installProvider方法中完成。通過ClassLoader創建provider對象,然後調用其attachInfo回調onCreate方法:
    private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
            ...
            try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
                if (packageInfo == null) {
                    // System startup case.
                    packageInfo = getSystemContext().mPackageInfo;
                }
                localProvider = packageInfo.getAppFactory()
                        .instantiateProvider(cl, info.name);
                ...
                localProvider.attachInfo(c, info);

provider創建完成,調用Application的onCreate方法:

try {
    mInstrumentation.callApplicationOnCreate(app);

至此,ContentProvider創建完成,其進程的Application也創建完成。使用ContentProvider時,實際上是通過獲得的IContentProvider接口去執行遠程調用,實際類型爲ContentProvider.Transport,其query方法:

@Override
public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
        @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
    ...
    try {
        return ContentProvider.this.query(
                uri, projection, queryArgs,
                CancellationSignal.fromTransport(cancellationSignal));

調用ContentProvider的query方法,然後通過Binder傳遞給client,完成了一次調用,其他方法類似。

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