跳转至

四大组件启动过程

关于四大组件的使用,可以参考我之前的几篇文章

本章主要从源码角度分析四大组件的工作过程。
本章源码基于Android 7.1。

1 四大组件概述

Android四大组件分别是Activity、Service、BroadcastReceiver以及ContentProvider。除了BroadcastReceiver之外,其他三个组件都必须在AndroidManifest中进行注册。对于BroadcastReceiver来说,它既可以在AndroidManifest中进行注册,也可以在代码中进行注册。在调用方式上,Activity、Service和BroadcastReceiver需要借助Intent,而ContentProvider不需要借助Intent。

Activity是一种展示组件,用户向用户直接展示一个界面,而且可以接受用户的输入信息从而进行交互。
Service是一种能够在后台执行长期运行操作的组件,它并没有UI界面。Service运行在宿主进程的主线程中,因此执行耗时的后台计算任务需要在单独的线程中去完成。
BroadcastReceiver是一种通讯组件,用于在不同组件甚至不同应用中传递消息。
ContentProvider是数据共享组件,用户向其他组件乃至其他应用共享数据。ContentProvider的CRUD操作需要处理好线程同步,因为这几个方法是在Binder线程池中调用的,另外ContentProvider组件不需要手动停止。

2 Activity的启动流程

我们启动Activity时,都会调用startActivity启动一个Activity。该方法有很多重载,但最后都会调用startActivityForResult(Intent, int, Bundle)方法:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // 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;
        }

        cancelInputsAndStartExitTransition(options);
        // 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的ActivityGroup类,它用来在一个界面中嵌入多个Activity,但是现在已经废弃,系统推荐使用Fragment来代替。我们接下来看一下mInstrumentation.execStartActivity方法:
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

从上面的代码可以看出,启动Activity的真正实现由ActivityManagerNative.getDefault().startActivity来完成。ActivityManagerService(AMS)继承至ActivityManagerNative,而ActivityManagerNative继承至Binder并实现了IActivityManager接口,所以AMS也是一个Binder。在ActivityManagerNative,AMS以单例的模式提供实例。

Info

AMS中IActivityManager、ActivityManagerNative、ActivityManagerProxy与ActivityManagerService之间的关系,其实就是.aidl这一套里面的角色之间的关系。
假如这里有IActivityManager.aidl,那么编译后会生成IActivityManager、IActivityManager.Stub、IActivityManager.Proxy;服务端ActivityManagerService会继承IActivityManager.Stub类,实现里面的方法。
这里面的对照关系如下:
IActivityManager → aidl编译后生成的IActivityManager
ActivityManagerNative → IActivityManager.Stub
ActivityManagerProxy → IActivityManager.Proxy
ActivityManagerService → 服务端IActivityManager.Stub的继承类

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;
    }
};
Singleton位于./frameworks/base/core/java/android/util/Singleton.java,其实现非常简单:
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}
从上面的分析可以看出,Activity的启动过程会由ActivityManagerNative转移到了AMS。

我们先后过头看一下第二段代码里面的checkStartActivityResult代码,因为后面越来越深入了,以免沉迷于后面忘记这段代码:

/** @hide */
public static void checkStartActivityResult(int res, Object intent) {
    if (res >= ActivityManager.START_SUCCESS) {
        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);
        case ActivityManager.START_PERMISSION_DENIED:
            throw new SecurityException("Not allowed to start activity "
                    + intent);
        case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
            throw new AndroidRuntimeException(
                    "FORWARD_RESULT_FLAG used while also requesting a result");
        case ActivityManager.START_NOT_ACTIVITY:
            throw new IllegalArgumentException(
                    "PendingIntent is not an activity");
        case ActivityManager.START_NOT_VOICE_COMPATIBLE:
            throw new SecurityException(
                    "Starting under voice control not allowed for: " + intent);
        case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
            throw new IllegalStateException(
                    "Session calling startVoiceActivity does not match active session");
        case ActivityManager.START_VOICE_HIDDEN_SESSION:
            throw new IllegalStateException(
                    "Cannot start voice activity on a hidden session");
        case ActivityManager.START_CANCELED:
            throw new AndroidRuntimeException("Activity could not be started for "
                    + intent);
        default:
            throw new AndroidRuntimeException("Unknown error code "
                    + res + " when starting " + intent);
    }
}
这段代码就是检查启动Activity的结果。如果是异常结果,抛出相应的错误。这些结果大部分都在ActivityStarter#startActivityLocked方法中返回。

我们接着看AMS的startActivity方法:

@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);
}
可以看出,Activity的启动又转移到了ActivityStarter中,startActivityMayWaitstartActivityLocked -> startActivityUnchecked -> ActivityStackSupervisor#resumeFocusedStackTopActivityLocked -> ActivityStack#resumeTopActivityUncheckedLocked -> resumeTopActivityInnerLocked -> ActivityStackSupervisor#startSpecificActivityLocked -> realStartActivityLocked。这一段代码比较多,我们简单的过一下调用流程就行,Activity的启动从ActivityStarter开始,经过ActivityStackSupervisor,到ActivityStack,然后返回ActivityStackSupervisor,最后调用realStartActivityLocked

ActivityStackSupervisor#startSpecificActivityLocked方法中会判断进程是否存在,不存在则会通过Zygote fork出一个进程。

realStartActivityLocked方法中有如下一段关键的代码:

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

app.thread的类型是IApplicationThread,它继承至IInterface接口,所以它是一个Binder类型的接口。ApplicationThread继承至ApplicationThreadNative,而ApplicationThreadNative继承了Binder并实现了IApplicationThread。ApplicationThreadNative就是AIDL模式下的IApplicationThread.Stub。

Info

ApplicationThread中IApplicationThread、ApplicationThreadNative、ApplicationThreadProxy与ApplicationThread之间的关系,其实就是.aidl这一套里面的角色之间的关系。和上面提到过的AMS的一样。
这里面的对照关系如下:
IApplicationThread → aidl编译后生成的IApplicationThread
ApplicationThreadNative → IApplicationThread.Stub
ApplicationThreadProxy → IApplicationThread.Proxy
ApplicationThread → 服务端IApplicationThread.Stub的继承类

Activity的启动过程最后回到了ApplicationThread中,我们看一下scheduleLaunchActivity方法:

// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@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);
}
该方法非常简单,就是发送一个LAUNCH_ACTIVITY消息给H这个Handler。

H对该消息的处理是调用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);
        ...
    } else {
        ...
    }
    ...
}
可以看出,最后通过performLaunchActivity方法完成了Activity的创建和启动,通过handleResumeActivity方法调用被启动Activity的onResume

performLaunchActivity方法完成了这几件事:
1.从ActivityClientRecord中获取获取待启动Activity的ComponentName

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

2.通过Instrumentation的newActivity方法使用类加载器创建Activity对象

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);
    }
}
Instrumentation的newActivity方法就是类加载器创建类实例(Activity)cl.loadClass(className).newInstance()

3.通过LoadedApk的makeApplication方法尝试创建Application对象

Application app = r.packageInfo.makeApplication(false, mInstrumentation);

// LoaderApk#makeApplication
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    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);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            throw new RuntimeException(
                "Unable to instantiate application " + appClass
                + ": " + e.toString(), e);
        }
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!instrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }

    // Rewrite the R 'constants' for all library apks.
    SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
            .getAssignedPackageIdentifiers();
    final int N = packageIdentifiers.size();
    for (int i = 0; i < N; i++) {
        final int id = packageIdentifiers.keyAt(i);
        if (id == 0x01 || id == 0x7f) {
            continue;
        }

        rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
    }

    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    return app;
}
通过makeApplication的实现可以看出,如果Application已经创建过,那么直接返回改实例。Application对象的创建也是Instrumentation的makeApplication方法,通过类加载器来实现的。然后会调用instrumentation.callApplicationOnCreate(app);方法,该方法会调用Application的onCreate()方法。

4.创建ContextImpl,然后调用Activity的attach方法完成一些重要元素的初始化

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);
ContextImpl是一个很重要的类,它是Context的具体实现,Context中大部分逻辑都是ContextImpl来完成的。ContextImpl是通过Activity的attach方法来完成关联的,除此之外,attach方法还完成Window的创建并建立和自己的联系。

5.调用Activity的一些回调方法

if (r.isPersistable()) {
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
    mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
    throw new SuperNotCalledException(
        "Activity " + r.intent.getComponent().toShortString() +
        " did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
    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()");
    }
}
mInstrumentation.callActivityOnCreate会调用Activity的performCreate,然后调用onCreate方法。 activity.performStart()会调用mInstrumentation.callActivityOnStart,然后调用activity.onStart()方法。 mInstrumentation.callActivityOnRestoreInstanceState会调用Activity的onRestoreInstanceState方法,然后在调用onRestoreInstanceState方法。

下图详细的描述了Activity的启动过程:

Activity的启动过程

一句话总结:
Activity的启动过程,我们从Context的startActivity说起,其实现是ContextImpl的startActivity,然后内部会通过Instrumentation来尝试启动Activity,这是一个跨进程过程,它会调用AMS的startActivity方法,当AMS校验完Activity的合法性后,会通过ApplicationThread回调到我们的进程,这也是一次跨进程过程,而ApplicationThread就是一个Binder。回调逻辑是在Binder线程池中完成,所以需要通过Handler H将其切回UI线程,第一个消息是LAUNCH_ACTIVITY,它对应着handleLaunchActivity,在这个方法里面完成了Activity的创建和启动。接着,在Activity的onResume中,Activity的内容将开始渲染到Window上面,然后开始绘制直到我们可以看见。

3 Service的启动流程

Service有两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于与其他组件交互。Service的这两种状态是可以共存的。

3.1 Service的start过程

Service的启动过程会从ContextWrapper#startService开始:

@Override
public ComponentName startService(Intent service) {
    return mBase.startService(service);
}
这里的mBase是一个ContextImpl。我们知道在Activity创建时会调用Activity#attach方法,attach方法刚开始就会调用ContextThemeWrapper#attachBaseContext(context),ContextThemeWrapper继承至ContextWrapper,该方法就是调用super.attachBaseContext(newBase)ContextWrapper#attachBaseContext的实现就是将传入参数保存起来。这种设计模式是一种桥接模式。

因此我们看一下ContextImpl#startService方法:

@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, mUser);
}

private ComponentName startServiceCommon(Intent service, UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        ComponentName cn = ActivityManagerNative.getDefault().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), getOpPackageName(), user.getIdentifier());
        if (cn != null) {
            if (cn.getPackageName().equals("!")) {
                throw new SecurityException(
                        "Not allowed to start service " + service
                        + " without permission " + cn.getClassName());
            } else if (cn.getPackageName().equals("!!")) {
                throw new SecurityException(
                        "Unable to start service " + service
                        + ": " + cn.getClassName());
            }
        }
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
warnIfCallingFromSystemProcess在系统进程直接调用像startService方法而不是startServiceAsUser时会打印warning log。在startServiceCommon中会通过ActivityManagerService#startService方法来启动Service,这是一个RPC。

我们接着看ActivityManagerService#startService方法:

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, String callingPackage, int userId)
        throws TransactionTooLargeException {
    enforceNotIsolatedCaller("startService");
    // Refuse possible leaked file descriptors
    if (service != null && service.hasFileDescriptors() == true) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }

    if (callingPackage == null) {
        throw new IllegalArgumentException("callingPackage cannot be null");
    }

    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
            "startService: " + service + " type=" + resolvedType);
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res = mServices.startServiceLocked(caller, service,
                resolvedType, callingPid, callingUid, callingPackage, userId);
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}
AMS会通过mServices完成Service后续的启动过程,mServices是一个ActiveServices对象,该对象是一个辅助AMS进行Service管理的类,包括Service的启动、绑定、停止等等。ActiveServicesstartServiceLocked方法调用了startServiceInnerLocked方法。

ActiveServices#startServiceInnerLocked方法如下所示:

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);
    if (error != null) {
        return new ComponentName("!!", error);
    }

    if (r.startRequested && addToStarting) {
        boolean first = smap.mStartingBackground.size() == 0;
        smap.mStartingBackground.add(r);
        r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
        if (DEBUG_DELAYED_SERVICE) {
            RuntimeException here = new RuntimeException("here");
            here.fillInStackTrace();
            Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
        } else if (DEBUG_DELAYED_STARTS) {
            Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
        }
        if (first) {
            smap.rescheduleDelayedStarts();
        }
    } else if (callerFg) {
        smap.ensureNotStartingBackground(r);
    }

    return r.name;
}
ServiceRecord描述的是一个Service记录,startServiceInnerLocked方法也没有完成具体的启动工作,其内部调用了bringUpServiceLockedbringUpServiceLocked又调用了realStartServiceLocked方法。该方法才是真正启动Service的方法:
private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    if (app.thread == null) {
        throw new RemoteException();
    }
    if (DEBUG_MU)
        Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                + ", ProcessRecord.uid = " + app.uid);
    r.app = app;
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

    final boolean newService = app.services.add(r);
    bumpServiceExecutingLocked(r, execInFg, "create");
    mAm.updateLruProcessLocked(app, false, null);
    mAm.updateOomAdjLocked();

    boolean created = false;
    try {
        if (LOG_SERVICE_START_STOP) {
            String nameTerm;
            int lastPeriod = r.shortName.lastIndexOf('.');
            nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
            EventLogTags.writeAmCreateService(
                    r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
        }
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startLaunchedLocked();
        }
        mAm.notifyPackageUse(r.serviceInfo.packageName,
                             PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
        Slog.w(TAG, "Application dead when creating service " + r);
        mAm.appDiedLocked(app);
        throw e;
    } finally {
        if (!created) {
            // Keep the executeNesting count accurate.
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);

            // Cleanup.
            if (newService) {
                app.services.remove(r);
                r.app = null;
            }

            // Retry.
            if (!inDestroying) {
                scheduleServiceRestartLocked(r, false);
            }
        }
    }

    if (r.whitelistManager) {
        app.whitelistManager = true;
    }

    requestServiceBindingsLocked(r, execInFg);

    updateServiceClientActivitiesLocked(app, null, true);

    // If the service is in the started state, and there are no
    // pending arguments, then fake up one so its onStartCommand() will
    // be called.
    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                null, null));
    }

    sendServiceArgsLocked(r, execInFg, true);

    if (r.delayed) {
        if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
        getServiceMap(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }

    if (r.delayedStop) {
        // Oh and hey we've already been asked to stop!
        r.delayedStop = false;
        if (r.startRequested) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                    "Applying delayed stop (from start): " + r);
            stopServiceLocked(r);
        }
    }
}
在此方法中,首先通过app.thread.scheduleCreateService方法创建Service对象并调用其onCreate方法,接着通过sendServiceArgsLocked方法调用Service的其他方法,这两个方法均是进程间通信。

我们先看一下app.thread.scheduleCreateService,app.thread实际上是ApplicationThread:

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);
}
该消息会使H调用ActivityThread#handleCreateService
private void handleCreateService(CreateServiceData data) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();

    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                + ": " + e.toString(), e);
        }
    }

    try {
        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

        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,
                ActivityManagerNative.getDefault());
        service.onCreate();
        mServices.put(data.token, service);
        try {
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to create service " + data.info.name
                + ": " + e.toString(), e);
        }
    }
}
该代码和Activity启动过程中performLaunchActivity很相似,它完成了这几项事情:

  1. 通过类加载器创建Service实例
  2. 创建Application对象并调用其onCreate方法
  3. 创建ContextImpl,然后调用Service的attach方法完成一些重要元素的初始化
  4. 调用Service的onCreate方法,然后将Service对象保存起来

接着我们回过头看一下ActiveServices#sendServiceArgsLocked方法,此方法会调用r.app.thread.scheduleServiceArgs,该方法会发送H.SERVICE_ARGS消息,H收到消息后会调用ActivityThread#handleServiceArgs

private void handleServiceArgs(ServiceArgsData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            if (data.args != null) {
                data.args.setExtrasClassLoader(s.getClassLoader());
                data.args.prepareToEnterProcess();
            }
            int res;
            if (!data.taskRemoved) {
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }

            QueuedWork.waitToFinish();

            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            ensureJitEnabled();
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to start service " + s
                        + " with " + data.args + ": " + e.toString(), e);
            }
        }
    }
}
在此方法中会调用Service的onStartCommand方法。至此,Service的start流程已经OK了。下图是随手画的流程图:

Service的start流程

3.2 Service的bind过程

和Service的start过程一样,bind过程也是从ContextWrapper开始:

@Override
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}
ContextImpl的bindService会调用bindServiceCommon方法。该方法如下:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
        handler, UserHandle user) {
    IServiceConnection sd;
    if (conn == null) {
        throw new IllegalArgumentException("connection is null");
    }
    if (mPackageInfo != null) {
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
    } else {
        throw new RuntimeException("Not supported in system context");
    }
    validateServiceIntent(service);
    try {
        IBinder token = getActivityToken();
        if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                && mPackageInfo.getApplicationInfo().targetSdkVersion
                < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            flags |= BIND_WAIVE_PRIORITY;
        }
        service.prepareToLeaveProcess(this);
        int res = ActivityManagerNative.getDefault().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());
        if (res < 0) {
            throw new SecurityException(
                    "Not allowed to bind to service " + service);
        }
        return res != 0;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
首先,会将ServiceConnection封装成为一个IServiceConnection对象。这是因为ServiceConnection是不能直接进行IPC的,而IServiceConnection的是一个LoadedApk#ServiceDispatcher#InnerConnection对象,它继承了IServiceConnection.Stub,因此可以进行RPC操作。ServiceDispatcher相当于一个中介,它内部保存了ServiceConnection的实例以及IServiceConnection实例,这样以后可以通过它彼此调用。

Service的bind过程会通过ActivityManagerService(AMS)的bindService方法来完成。接下来又完成了一系列调用,先后经过ActiveServices#bindServiceLocked -> bringUpServiceLocked -> realStartServiceLocked。在最后的方法中,其执行逻辑与startService的逻辑比较相似,都是通过ApplicationThread来完成Service的创建以及调用其onCreate方法。

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

回到最初的ActivityServices#bindServiceLocked方法中,在bringUpServiceLocked方法调用之后,会调用requestServiceBindingLocked方法。在此方法中会调用r.app.thread.scheduleBindService来绑定的。

public final void scheduleBindService(IBinder token, Intent intent,
        boolean rebind, int processState) {
    updateProcessState(processState, false);
    BindServiceData s = new BindServiceData();
    s.token = token;
    s.intent = intent;
    s.rebind = rebind;

    if (DEBUG_SERVICE)
        Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
    sendMessage(H.BIND_SERVICE, s);
}

H在接收到BIND_SERVICE消息后,会调用handleBindService方法。该方法如下所示:

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);
                    ActivityManagerNative.getDefault().publishService(
                            data.token, data.intent, binder);
                } else {
                    s.onRebind(data.intent);
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
                ensureJitEnabled();
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to bind to service " + s
                        + " with " + data.intent + ": " + e.toString(), e);
            }
        }
    }
}
在上面,会先调用Service#onBind方法,onBind方法会返回一个Binder对象,该对象会通过AMS的publishService方法调用客户端ServiceConnection的onServiceConnected方法将Binder对象返回给客户端。这个具体的过程是在ActiveServices#publishServiceLocked方法中,该方法最核心的一行代码是:
c.conn.connected(r.name, service);
c是ConnectionRecord对象,c.conn是IServiceConnection对象,实际上是ServiceDispatcher.InnerConnection对象。所以接下来我们看一下ServiceDispatcher.InnerConnection的connected方法。
public void connected(ComponentName name, IBinder service) throws RemoteException {
    LoadedApk.ServiceDispatcher sd = mDispatcher.get();
    if (sd != null) {
        sd.connected(name, service);
    }
}
这里又调用了LoadedApk.ServiceDispatcher#connected方法。
public void connected(ComponentName name, IBinder service) {
    if (mActivityThread != null) {
        mActivityThread.post(new RunConnection(name, service, 0));
    } else {
        doConnected(name, service);
    }
}
这里无论是RunConnection里面的run方法也会调用doConnected方法。因此我们最后看看这个方法:
public void doConnected(ComponentName name, IBinder service) {
    ServiceDispatcher.ConnectionInfo old;
    ServiceDispatcher.ConnectionInfo info;

    synchronized (this) {
        if (mForgotten) {
            // We unbound before receiving the connection; ignore
            // any connection received.
            return;
        }
        old = mActiveConnections.get(name);
        if (old != null && old.binder == service) {
            // Huh, already have this one.  Oh well!
            return;
        }

        if (service != null) {
            // A new service is being connected... set it all up.
            info = new ConnectionInfo();
            info.binder = service;
            info.deathMonitor = new DeathMonitor(name, service);
            try {
                service.linkToDeath(info.deathMonitor, 0);
                mActiveConnections.put(name, info);
            } catch (RemoteException e) {
                // This service was dead before we got it...  just
                // don't do anything with it.
                mActiveConnections.remove(name);
                return;
            }

        } else {
            // The named service is being disconnected... clean up.
            mActiveConnections.remove(name);
        }

        if (old != null) {
            old.binder.unlinkToDeath(old.deathMonitor, 0);
        }
    }

    // If there was an old service, it is now disconnected.
    if (old != null) {
        mConnection.onServiceDisconnected(name);
    }
    // If there is a new service, it is now connected.
    if (service != null) {
        mConnection.onServiceConnected(name, service);
    }
}
很显然,在最后调用了mConnection.onServiceConnected(name, service);这样就完成了ServiceConnection的回调。 至此Service的bind启动方式也已经分析完了。下面上一张大致流程图:

Service的bind流程

4 BroadcastReceiver的工作过程

BroadcastReceiver的工作过程分为两方面的内容:注册过程;发送以及接收过程。

4.1 BroadcastReceiver的注册过程

4.1.1 BroadcastReceiver的动态注册过程

BroadcastReceiver的动态注册过程始于registerReceiver方法。同上面几大组件启动过程一样,该方法由ContextImpl实现,并最后调用ContextImpl#registerReceiverInternal方法:

// ./frameworks/base/core/java/android/app/ContextImpl.java

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context) {
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = mPackageInfo.getReceiverDispatcher(
                receiver, context, scheduler,
                mMainThread.getInstrumentation(), true);
        } else {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = new LoadedApk.ReceiverDispatcher(
                    receiver, context, scheduler, null, true).getIIntentReceiver();
        }
    }
    try {
        final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName,
                rd, filter, broadcastPermission, userId);
        if (intent != null) {
            intent.setExtrasClassLoader(getClassLoader());
            intent.prepareToEnterProcess();
        }
        return intent;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
上面的代码,首先会将BroadcastReceiver包装为IIntentReceiver对象,然后将这个对象向AMS进行注册。IIntentReceiver是一个Binder接口,其具体实现类是LoadApk.ReceiverDispatcher.InnerReceiver,因为AMS的注册过程是一个IPC过程,所以直接使用BroadcastReceiver是不可能的进行跨进程传递的。ReceiverDispatcher内部同时会持有BroadcastReceiver和IIntentReceiver.Stub两个对象的实例,这样当接收到广播时,ReceiverDispatcher可以很方便的调用BroadcastReceiver的onReceiver方法,具体的接收逻辑会在下一节中进行介绍。

我们接着研究上面包装部分的代码。
首先会直接通过mPackageInfo.getReceiverDispatcher来获取IIntentReceiver的对象实例。如果获取不到,则会new一个该对象,并调用其getIIntentReceiver方法。其实,mPackageInfo.getReceiverDispatcher方法的内部也会根据情况会new一个该对象。

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
        Context context, Handler handler,
        Instrumentation instrumentation, boolean registered) {
    synchronized (mReceivers) {
        LoadedApk.ReceiverDispatcher rd = null;
        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
        if (registered) {
            map = mReceivers.get(context);
            if (map != null) {
                rd = map.get(r);
            }
        }
        if (rd == null) {
            rd = new ReceiverDispatcher(r, context, handler,
                    instrumentation, registered);
            if (registered) {
                if (map == null) {
                    map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                    mReceivers.put(context, map);
                }
                map.put(r, rd);
            }
        } else {
            rd.validate(context, handler);
        }
        rd.mForgotten = false;
        return rd.getIIntentReceiver();
    }
}

真正实现广播注册的代码在AMS中,我们看一下AMS的registerReceiver方法。该方法比较长:

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
    enforceNotIsolatedCaller("registerReceiver");
    ArrayList<Intent> stickyIntents = null;
    ProcessRecord callerApp = null;
    int callingUid;
    int callingPid;
    synchronized(this) {
        // 获取callingUid、callingPid
        if (caller != null) {
            callerApp = getRecordForAppLocked(caller);
            ...
            callingUid = callerApp.info.uid;
            callingPid = callerApp.pid;
        } else {
            callerPackage = null;
            callingUid = Binder.getCallingUid();
            callingPid = Binder.getCallingPid();
        }

        // 收集当前用户的可与action匹配的粘性广播的Intent(该类广播已经被遗弃,因为安全以及其他的一些问题)
        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
        Iterator<String> actions = filter.actionsIterator();
        if (actions == null) {
            ArrayList<String> noAction = new ArrayList<String>(1);
            noAction.add(null);
            actions = noAction.iterator();
        }
        // Collect stickies of users
        int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
        while (actions.hasNext()) {
            String action = actions.next();
            for (int id : userIds) {
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                if (stickies != null) {
                    ArrayList<Intent> intents = stickies.get(action);
                    if (intents != null) {
                        if (stickyIntents == null) {
                            stickyIntents = new ArrayList<Intent>();
                        }
                        stickyIntents.addAll(intents);
                    }
                }
            }
        }
    }

    // 过滤不能匹配的Intent
    ArrayList<Intent> allSticky = null;
    if (stickyIntents != null) {
        final ContentResolver resolver = mContext.getContentResolver();
        // Look for any matching sticky broadcasts...
        for (int i = 0, N = stickyIntents.size(); i < N; i++) {
            Intent intent = stickyIntents.get(i);
            // If intent has scheme "content", it will need to acccess
            // provider that needs to lock mProviderMap in ActivityThread
            // and also it may need to wait application response, so we
            // cannot lock ActivityManagerService here.
            if (filter.match(resolver, intent, true, TAG) >= 0) {
                if (allSticky == null) {
                    allSticky = new ArrayList<Intent>();
                }
                allSticky.add(intent);
            }
        }
    }

    // 第一个粘性Intent可以直接返回给客户端
    // The first sticky in the list is returned directly back to the client.
    Intent sticky = allSticky != null ? allSticky.get(0) : null;
    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
    if (receiver == null) {
        return sticky;
    }

    synchronized (this) {
        if (callerApp != null && (callerApp.thread == null
                || callerApp.thread.asBinder() != caller.asBinder())) {
            // Original caller already died
            return null;
        }
        // 获取Receiver对应的List
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        if (rl == null) {
            // 如果List为空,则新建一个List,然后加入到mRegisteredReceivers中
            rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                    userId, receiver);
            // 如果对应进程不为空,那么将ReceiverList添加进去
            // 否者说明receiver已经死亡了,死亡代理会取消注册该receiver;
            // 如果上一步发生异常,返回sticky这个粘性Intent
            if (rl.app != null) {
                rl.app.receivers.add(rl);
            } else {
                try {
                    receiver.asBinder().linkToDeath(rl, 0);
                } catch (RemoteException e) {
                    return sticky;
                }
                rl.linkedToDeath = true;
            }
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        } else if (rl.uid != callingUid) {
            throw new IllegalArgumentException(
                    "Receiver requested to register for uid " + callingUid
                    + " was previously registered for uid " + rl.uid);
        } else if (rl.pid != callingPid) {
            throw new IllegalArgumentException(
                    "Receiver requested to register for pid " + callingPid
                    + " was previously registered for pid " + rl.pid);
        } else if (rl.userId != userId) {
            throw new IllegalArgumentException(
                    "Receiver requested to register for user " + userId
                    + " was previously registered for user " + rl.userId);
        }
        // 保存BroadcastFilter
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId);
        rl.add(bf);
        if (!bf.debugCheck()) {
            Slog.w(TAG, "==> For Dynamic broadcast");
        }
        mReceiverResolver.addFilter(bf);

        // Enqueue broadcasts for all existing stickies that match
        // this filter.
        if (allSticky != null) {
            ArrayList receivers = new ArrayList();
            receivers.add(bf);

            final int stickyCount = allSticky.size();
            for (int i = 0; i < stickyCount; i++) {
                Intent intent = allSticky.get(i);
                BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                        null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,
                        null, 0, null, null, false, true, true, -1);
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        }

        return sticky;
    }
}
需要注意的是,sticky broadcast已经由于没有不安全、没有保护以及其他问题已经被遗弃了,所以大量的关于sticky的代码可以忽略。上面这段代码的核心代码只有下面的一段了。这段代码的是:
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
    mRegisteredReceivers.put(receiver.asBinder(), rl);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
        permission, callingUid, userId);
rl.add(bf);
mReceiverResolver.addFilter(bf);
很显然,该方法会将InnerReceiver和IntentFilter保存起来,这样就完成了注册过程。

4.1.2 BroadcastReceiver的静态注册过程

静态广播在应用安装的时候由系统自动完成注册,这段代码在PackageManagerService(PMS)中。
// TODO 待我读完PMS再回来

4.2 Broadcast的发送以及接收过程

广播的类型包括:普通广播、有序广播以及粘性广播。

Broadcast的发送最后实现在ContextImpl中大量send方法开始。

@Override
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess(this);
        ActivityManagerNative.getDefault().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                getUserId());
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
我们可以看到,ContextImpl会调用AMS的broadcastIntent方法进行处理。接下来我们看看AMS里面的方法:
public final int broadcastIntent(IApplicationThread caller,
        Intent intent, String resolvedType, IIntentReceiver resultTo,
        int resultCode, String resultData, Bundle resultExtras,
        String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean serialized, boolean sticky, int userId) {
    enforceNotIsolatedCaller("broadcastIntent");
    synchronized(this) {
        intent = verifyBroadcastLocked(intent);

        final ProcessRecord callerApp = getRecordForAppLocked(caller);
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        int res = broadcastIntentLocked(callerApp,
                callerApp != null ? callerApp.info.packageName : null,
                intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                requiredPermissions, appOp, bOptions, serialized, sticky,
                callingPid, callingUid, userId);
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}
上面的代码调用了broadcastIntentLocked方法,这个方法很长,在Android 7.1的代码中有近600行。该方法里面的注释非常详实,在校验状态、处理系统应用广播等等之后,将广播插入了广播队列中:
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
        callerPackage, callingPid, callingUid, resolvedType,
        requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
        resultData, resultExtras, ordered, sticky, false, userId);
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
    queue.enqueueOrderedBroadcastLocked(r);
    queue.scheduleBroadcastsLocked();
}
当然,如果没有接受者可以接受到这条广播,那么装作它已经发送了。
// There was nobody interested in the broadcast, but we still want to record
// that it happened.
if (intent.getComponent() == null && intent.getPackage() == null
        && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
    // This was an implicit broadcast... let's record it for posterity.
    addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}

我们回过头看一下queue.scheduleBroadcastsLocked()这个方法,该方法是真正开始处理广播的方法:

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;
}
我们可以看到,这个方法仅仅是发送了BROADCAST_INTENT_MSG消息。在mHandler中关于此消息的处理是调用了processNextBroadcast方法,这个方法中有这么一段处理无序广播的代码:
while (mParallelBroadcasts.size() > 0) {
    r = mParallelBroadcasts.remove(0);
    r.dispatchTime = SystemClock.uptimeMillis();
    r.dispatchClockTime = System.currentTimeMillis();
    final int N = r.receivers.size();
    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
            + mQueueName + "] " + r);
    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);
    }
    addBroadcastToHistoryLocked(r);
    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
            + mQueueName + "] " + r);
}
在上面的代码中,无序广播列表mParallelBroadcasts会被遍历,然后一个个的调用deliverToRegisteredReceiverLocked方法。该方法会将广播发送给注册过的接受者:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
        BroadcastFilter filter, boolean ordered, int index) {
    ...
    try {
        if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
            if (ordered) {
                skipReceiverLocked(r);
            }
        } else {
            performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                    new Intent(r.intent), r.resultCode, r.resultData,
                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
        }
    } catch (RemoteException e) {
    ...
    }
}
在上述方法中,进行一系列的权限检查之后,会调用performReceiveLocked方法来完成具体的发送过程:
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);
            // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
            // DeadObjectException when the process isn't actually dead.
            //} catch (DeadObjectException ex) {
            // Failed to call into the process.  It's dying so just let it die and move on.
            //    throw ex;
            } catch (RemoteException ex) {
                // Failed to call into the process. It's either dying or wedged. Kill it gently.
                synchronized (mService) {
                    Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                            + " (pid " + app.pid + "). Crashing it.");
                    app.scheduleCrash("can't deliver broadcast");
                }
                throw ex;
            }
        } else {
            // Application has died. Receiver doesn't exist.
            throw new RemoteException("app.thread must not be null");
        }
    } else {
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
    }
}
这里会调用app.thread.scheduleRegisteredReceiver,我们知道app.thread指的就是ApplicationThread,因此操作又回到了应用本身。我们接着看下面的代码:
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);
}
这里调用了receiver.performReceive方法,这个方法在/frameworks/base/core/java/android/app/LoadedApk.javaLoadedApk#ReceiverDispatcher#InnerReceiver
@Override
public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final LoadedApk.ReceiverDispatcher rd;
    if (intent == null) {
        Log.wtf(TAG, "Null intent received");
        rd = null;
    } else {
        rd = mDispatcher.get();
    }
    if (rd != null) {
        rd.performReceive(intent, resultCode, data, extras,
                ordered, sticky, sendingUser);
    } else {
        ...
    }
}
可以看到,InnerReceiver又调用了LoadedApk.ReceiverDispatcher#performReceive方法。
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) {
        Log.wtf(TAG, "Null intent received");
    } else {
        if (ActivityThread.DEBUG_BROADCAST) {
            int seq = intent.getIntExtra("seq", -1);
            Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                    + " seq=" + seq + " to " + mReceiver);
        }
    }
    if (intent == null || !mActivityThread.post(args)) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManagerNative.getDefault();
            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                    "Finishing sync broadcast to " + mReceiver);
            args.sendFinished(mgr);
        }
    }
}
Args是一个实现了Runnable接口的类,上面这段代码关键点就在mActivityThread.post(args)这句代码。mActivityThread在ContextImpl#registerReceiverInternal方法中可以看出,它就是mMainThread.getHandler(),也就是mH。因此我们可以看看Args#run方法
public void run() {
    ...
    try {
        ClassLoader cl =  mReceiver.getClass().getClassLoader();
        intent.setExtrasClassLoader(cl);
        intent.prepareToEnterProcess();
        setExtrasClassLoader(cl);
        receiver.setPendingResult(this);
        receiver.onReceive(mContext, intent);
    } catch (Exception e) {
        ...
    }
}
很显然,这个时候BroadcastReceiver的onReceive方法就被执行了,也就是说明接收到广播了。同时,由于被mHpost处理了一下,因此这个方法是在主线程被执行的。到目前为止,广播的发送、注册、接收都已经大致的缕了一下。

5 ContentProvider的工作过程

当ContentProvider所在的进程程启动时,ContentProvider会同时启动并被发布到AMS中。ContentProvider的onCreate要优先于ApplicationonCreate方法执行。

Content Provider启动流程图

访问ContentProvider需要使用ContentResolver,这是一个抽象类。我们通过ContextgetContentResolver方法获取到的是 是ApplicationContentResolver。我们可以从Context的实现类ContextImpl#getContentResolver中直接看到。

class ContextImpl extends Context {
    ...
    private final ApplicationContentResolver mContentResolver;
    ...
    @Override
    public ContentResolver getContentResolver() {
        return mContentResolver;
    }
}

ContentProvider所在的进程未启动时,第一次访问它就会触发ContentProvider的创建,当然也伴随着ContentProvider所在进程的启动。通过ContentProvider的四个方法都可以触发其创建过程,我们这里选择query方法。

ContentResolverquery方法会首先获取IContentProvider对象,这个类型的对象有两个——通过acquireUnstableProvider方法获取的unstableProvider以及通过acquireProvider方法获取的stableProvider。但这两个方法最后都是通过ActivityThread#acquireProvider方法来获取ContentProvider

private static final class ApplicationContentResolver extends ContentResolver {
    private final ActivityThread mMainThread;
    private final UserHandle mUser;

    public ApplicationContentResolver(
            Context context, ActivityThread mainThread, UserHandle user) {
        super(context);
        mMainThread = Preconditions.checkNotNull(mainThread);
        mUser = Preconditions.checkNotNull(user);
    }
    ...
    @Override
    protected IContentProvider acquireProvider(Context context, String auth) {
        return mMainThread.acquireProvider(context,
                ContentProvider.getAuthorityWithoutUserId(auth),
                resolveUserIdFromAuthority(auth), true);
    }

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

下面看下ActivityThread#acquireProvider的源码

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

    // There is a possible race here.  Another thread may try to acquire
    // the same provider at the same time.  When this happens, we want to ensure
    // that the first one wins.
    // Note that we cannot hold the lock while acquiring and installing the
    // provider since it might take a long time to run and it could also potentially
    // be re-entrant in the case where the provider is in the same process.
    IActivityManager.ContentProviderHolder holder = null;
    try {
        holder = ActivityManagerNative.getDefault().getContentProvider(
                getApplicationThread(), auth, userId, stable);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    if (holder == null) {
        Slog.e(TAG, "Failed to find provider info for " + auth);
        return null;
    }

    // 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;
}
上面的代码会首先从ActivityThread中查找目标ContentProvider是否已经存在,如果存在则直接返回。ActivityThread通过mProviderMap存储已经启动的ContentProvider对象。
final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
        = new ArrayMap<ProviderKey, ProviderClientRecord>();
如果ContentProvider没有启动,那么发送一个RPC给AMS让其启动ContentProvider,最后通过installProvider方法进行install并修改引用计数。

我们知道,启动ContentProvider会首先启动ContentProvider所在的进程,进程启动是由AMS的startProcessLocked方法里面的Process#start方法来完成的。在Process#start方法中会通过LocalSocket zygoteSocket写入参数,从而完成新进程的启动。

新进程启动后其入口方法ActivityThread#main方法就会调用。

public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    SamplingProfilerIntegration.start();

    // CloseGuard defaults to true and can be quite spammy.  We
    // disable it here, but selectively enable it later (via
    // StrictMode) on debug builds, but using DropBox, not logs.
    CloseGuard.setEnabled(false);

    Environment.initForCurrentUser();

    // Set the reporter for event logging in libcore
    EventLogger.setReporter(new EventLoggingReporter());

    // Make sure TrustedCertificateStore looks in the right place for CA certificates
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    Process.setArgV0("<pre-initialized>");

    Looper.prepareMainLooper();

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

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

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

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

    throw new RuntimeException("Main thread loop unexpectedly exited");
}
ActivityThreadmain是一个静态方法,它内部会创建ActivityThread的实例并调用attach方法进行一系列初始化操作,接着就开始进行消息循环了。ActivityThreadattach方法会将自己通过AMS的attachApplication方法跨进程传递给AMS,最终AMS会完成ContentProvider的创建过程。中间的创建过程可以参考本节开始的图。

在经过一系列周折之后,我们又回到了ActivityThread#handleBindApplication方法。该方法完成了ApplicationContentProvider的创建,该方法可以氛围如下四个部分:

1.创建ContextImplInstrumentation

final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

// Continue loading instrumentation.
if (ii != null) {
    ...
    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);
   ...
} else {
    mInstrumentation = new Instrumentation();
}

2.创建Application

Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;

3.启动当前进程的ContentProvider并调用其onCreate方法

if (!ArrayUtils.isEmpty(data.providers)) {
    installContentProviders(app, data.providers);
    // For process that contains content providers, we want to
    // ensure that the JIT is enabled "at some point".
    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}

installContentProviders完成了ContentProvider的启动工作。该方法如下所示:

private void installContentProviders(
        Context context, List<ProviderInfo> providers) {
    final ArrayList<IActivityManager.ContentProviderHolder> results =
        new ArrayList<IActivityManager.ContentProviderHolder>();

    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());
        }
        IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
        if (cph != null) {
            cph.noReleaseNeeded = true;
            results.add(cph);
        }
    }

    try {
        ActivityManagerNative.getDefault().publishContentProviders(
            getApplicationThread(), results);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}
首先该方法会遍历当前进程的ProviderInfo列表,并一一调用installProvider方法完成启动,接着将已经启动的ContentProvider发布到AMS,AMS会保存到ProviderMap mProviderMap中,这样外部调用者可以直接从AMS获取ContentProvider

ContentProvider的创建在installProvider方法中:

try {
    final java.lang.ClassLoader cl = c.getClassLoader();
    localProvider = (ContentProvider)cl.
        loadClass(info.name).newInstance();
    provider = localProvider.getIContentProvider();
    if (provider == null) {
        Slog.e(TAG, "Failed to instantiate class " +
              info.name + " from sourceDir " +
              info.applicationInfo.sourceDir);
        return null;
    }
    if (DEBUG_PROVIDER) Slog.v(
        TAG, "Instantiating local provider " + info.name);
    // XXX Need to create the correct context for this provider.
    localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
    if (!mInstrumentation.onException(null, e)) {
        throw new RuntimeException(
                "Unable to get provider " + info.name
                + ": " + e.toString(), e);
    }
    return null;
}
在完成ContentProvider对象的创建后,还会通过ContentProvider#attachInfo方法来调用其onCreate方法。
/**
 * After being instantiated, this is called to tell the content provider
 * about itself.
 *
 * @param context The context this provider is running in
 * @param info Registered information about this content provider
 */
public void attachInfo(Context context, ProviderInfo info) {
    attachInfo(context, info, false);
}

private void attachInfo(Context context, ProviderInfo info, boolean testing) {
    mNoPerms = testing;

    /*
     * Only allow it to be set once, so after the content service gives
     * this to us clients can't change it.
     */
    if (mContext == null) {
        mContext = context;
        if (context != null) {
            mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
                    Context.APP_OPS_SERVICE);
        }
        mMyUid = Process.myUid();
        if (info != null) {
            setReadPermission(info.readPermission);
            setWritePermission(info.writePermission);
            setPathPermissions(info.pathPermissions);
            mExported = info.exported;
            mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0;
            setAuthorities(info.authority);
        }
        ContentProvider.this.onCreate();
    }
}

到此为止,ContentProvider已经完成了创建,其onCreate也调用完毕,ContentProvider已经启动完成了。

4.调用Application#onCreate方法

回到ActivityThread#handleBindApplication方法中:

try {
    mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
    if (!mInstrumentation.onException(app, e)) {
        throw new RuntimeException(
            "Unable to create application " + app.getClass().getName()
            + ": " + e.toString(), e);
    }
}

经过上面的四个步骤,ContentProvider以及其所在的Application已经成功启动,其他应用可以通过AMS来访问这个ContentProvider了。

需要注意的是,这里的ContentProvider并不是原始的ContentProvider,而是它的Binder类型的对象IContentProviderIContentProvider的具体实现是ContentProviderNativeContentProvider.Transport,后者继承了前者。其他应用调用IContentProviderquery方法最终会以IPC的方式调用到ContentProvider.Transportquery方法,query方法的执行结果在通过Binder返回给调用者,这样整个调用过程就完成了。


最后更新: 2020年1月14日

评论