《Android 开发艺术探索》 09-四大组件的工作过程

抄书系列

Posted by Suzeyu on 2016-08-16

第九章: 还原四大组件的本质

blog相关代码

四大组件的运行状态

四大组件中除了BroadcastReceiver以外, 其余的三种组件都必须在AndroidManifest中注册, 对于BroadcastReceiver来说, 既可以在清单文件中注册, 也可以通过代码来注册. 在调用形式上除了ContentProvider不需要借助Intent. 其余的三大组件都需要Intent

Activity是一种展示型组件, 用于向用户直接地展示一个界面, 并且可以接收用户的输入信息从而进行交互. Activity是最重要的一种组件, 对于用户来说它就是应用的全部, 因为其他三大组件对用户来说是无法感知的. Activity的启动由Intent触发, 其中Intent可以分为显式和隐式. 显式Intent可以明确的指向一个Activity, 而隐式Intent则指向一个或者多个Activity组件. 或者是没有Activity组件可以处理这个隐式的Intent. 一个Activity具有特定的启动模式. 也可以通过finish来停止. 总结来说, Activity组件的主要作用是展示一个界面并和用户交互, 它扮演的是一种前台界面的角色.


Service是一种计算型组件, 用于后台执行一系列计算任务. 运行在后台,用户是无法感知的. ServiceActivity的不同: Activity组件只有一种运行模式,即Activity处于启动状态, 但是Service组件有两种状态: 启动状态绑定状态.

  • Service处于启动状态时, 这个时候Service内部可以做一些后台计算. 尽管Service组件是用于执行后台计算的, 但是它本身是运行在主线程的. 因此单独的耗时操作仍然需要单独的线程去执行.
  • Service处于绑定状态时, 内部同样可以进行后台计算, 但是处于这种状态时, 外界可以很方便的和Service组件进行通信.

    Service可以停止, 需要灵活采用stopServiceunBindService


BroadcastReceiver是一种消息型组件, 用于在不同的组件乃至不同的应用之间传递消息. 同样无法被用户感知, 因为是运行在系统内部, 广播的注册方式有两种:静态注册动态注册

  • 静态注册: 在清单文件中进行注册广播, 这种广播在应用安装时会被系统解析, 此种形式的广播不需要应用启动就可以接收到相应的广播.
  • 动态注册: 需要通过Context.registerReceiver()来实现, 并在不需要的时候通过Context.unRegisterReceiver()来解除广播. 此种形态的广播要应用启动才能注册和接收广播. 在实际开发中通过Context的一系列的send方法来发送广播, 被发送的广播会被系统发送给感兴趣的广播接收者, 发送和接收的过程的匹配是通过广播接收者的<intent-filter>来描述的.

    可以实现低耦合的观察者模式, 观察者和被观察者之间可以没有任何耦合. 但广播不适合来做耗时操作.


ContentProvider是一种数据共享组件, 用于向其他组件乃至其他应用共享数据. 无法被用户感知. 对于内容提供者来说, 它只需要实现增删改查四种基本操作, 在它内部维持着一份数据集合, 这个数据集合既可以通过数据库来实现, 也可以采用其他任何类型来实现, 例如list或者map. ContentProvider对数据集合的具体实现并没有任何要求.

要注意处理好内部的insert, delete, update, query方法的线程同步, 因为这几个方法是在Binder线程池被调用.

Activity的工作过程

虽然要打开一个Activity很简单, 但是不应该只是局限于表面. 了解其内部走向构成.所以一切从startActivity(intent)这个方法开始.

startActivity()有好几种重载方式但是最终都是调用startActivityForResult()方法.

注意这里分析的是5.0版本的源码, 和6.0源码实现稍微不同

首先看startActivityForResult()

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
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) {
mStartedActivity = true;
}
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
if (decor != null) {
decor.cancelPendingInputEvents();
}
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
if (options != null && !isTopOfTask()) {
mActivityTransitionState.startExitOutTransition(this, options);
}
}

关注mParent==null的分支. mParent代表的是ViewGroup, ActivityGroup最开始被用来在一个界面中嵌入多个子Activity, 在API13已经被废弃. 系统推荐使用Fragment代替ActivityGroup. 注意mMainThread.getApplicationThread()这个参数, 它的参数类型是ApplicationThread, ApplicationThreadActivityThread的一个内部类.

看一下Instrumentation#execStartActivity()这个方法

public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
// 启动Activity的真正实现
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) {
}
return null;
}

代码中真正启动Activity的真正实现是由ActivityManagerNative.getDefault().startActivity()方法完成的. 后面对ActivityManagerService简称AMS. AMS继承自ActivityManagerNative(), 而ActivityManagerNative()继承自Binder并实现了IActivityManager这个Binder接口, 因此AMS也是一个Binder, 它是IActivityManager的具体实现.

由于ActivityManagerNative.getDefault()本质是一个IActivityManager类型的Binder对象, 因此具体实现是AMS. 在ActivityManagerNative中, AMS这个Binder对象采用单例模式对外提供, Singleton是一个单例封装类. 第一次调用它的get()方法时会通过create方法来初始化AMS这个Binder对象, 在后续调用中会返回这个对象. 具体实现如下代码.

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

由上可以看到关于Activity的启动是由ActivityManagerNative.getDefault()来启动的, 而ActivityManagerNative.getDefault()实际上是AMS, 所以Activity的启动过程又被转移到了AMS中, 接下来查看AMS中的startActivity()方法.

在分析AMS#startActivity()之前, 是否在开始时候碰到过Activity没有在清单文件中声明然后崩溃的现象? 这个步骤是在Instrumentation#execStartActivity()刚才分析ActivityManagerNative.getDefault().startActivity()的下一步. 有一个checkStartActivityResult(),看名字应该是检查的类, 看一下实现.

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);
default:
throw new AndroidRuntimeException("Unknown error code "
+ res + " when starting " + intent);
}
}

看出这个方法是一言不合就抛异常. 看ActivityManager.START_CLASS_NOT_FOUND这个判断分支抛出的异常是不是很眼熟? 对就是没有在清单文件中注册就在这里抛出. 所以这个方法就是检查启动Activity的结果.

回到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 options) {
// 直接调用下面方法
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
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 options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}

Activity启动过程经过两次转移, 最后又转移到了mStackSupervisor.startActivityMayWait()这个方法, 所属类为ActivityStackSupervisor. 在startActivityMayWait()内部又调用了startActivityLocked()这里会返回结果码就是之前checkStartActivityResult()用到的. 继续跟进方法最后会调用startActivityUncheckedLocked(), 然后又调用了ActivityStack#resumeTopActivityLocked(). 这个时候启动过程已经从ActivityStackSupervisor转移到了ActivityStack类中.

具体实现

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
mService.updateSleepIfNeededLocked();
}
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}

从上可以看到result是根据调用的resumeTopActivityInnerLocked()返回, 而resumeTopActivityInnerLocked()又调用了ActivityStackSupervisor#startSpecificActivityLocked()方法. 看一下这个方法:

void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
// 继续进入!!!
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}

这个方法又进入了realStartActivityLocked(). 在这个方法中有如下一段代码:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
r.icicle, r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);

先整理一下刚才的调用过程, 我已经照着书上跟的不知所以然了…. = =

继续看刚才app.thread.scheduleLaunchActivity()这个方法. 其中app.thread类型为IApplicationThread, 这个玩意继承了IInterface接口, 所以他也是一个Binder类型的接口接口. 从IApplicationThread声明的接口方法可以看出, 其内部包含了大量启动和停止Activity的接口, 此外还包含了Service的启动与停止. 可以猜想, IApplicationThread这个Binder接口的是实现者完成了大量和Activity以及Service启动和停止的相关功能.

IApplicationThread的实现者是哪个类? 在ActivityThread中的内部类有一个ApplicationThread,看看定义

private class ApplicationThread extends ApplicationThreadNative
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread

可以看到ApplicationThread的继承关系, 而查看ApplicationThreadNative的作用其实和系统AIDL文件生成的类是一样的.

ApplicationThreadNative的内部, 还有一个ApplicationThreadProxy类, 眼熟吧在第二章讲解的时候aidl生成的java文件中也有一个内部的代理类. 所以ApplicationThreadNative就是IApplicationThread的实现者, 由于ApplicationThreadNative被系统定义为抽象类, 所以ApplicationThread就成了IApplicationThread的实现者


绕了一大圈, Activity启动过程最终回到了ApplicationThread中, ApplicationThread通过scheduleLaunchActivity()来启动Activity.

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, 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;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}

这段代码做的就是封装一个Activity的记录信息交给名字叫H的一个Handler对象去处理, 继续跟进看看里面的实现

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}

额, 没啥好瞅的就是封装一个message发送了一个消息. 好吧 那看看Handler接收的时候是如何处理的吧. 这个类里面对Handler进行了包装, 包装的类就是一个H的内部类.

private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
//这里省略一堆常量声明
//在省略一堆switch分支, 直接看具体的消息处理
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PAUSE_ACTIVITY_FINISHING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&1) != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
//这里又省去了一大坨的case分支
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}

我们目前只关心LAUNCH_ACTIVITY这个标记, 这个内部我们可以看到通过handleLaunchActivity()方法来实现. 这个方法内部通过PerformLaunchActivity()方法最终完成了Activity对象的创建和启动过程. 并且ActivityThread通过handleResumeActivity()方法来调用被启动的onResume()这一生命周期方法.

那么PerformLaunchActivity()究竟做了那几件事情完成了Activity的形成呢.


1. 从ActivityClientRecord中获取待启动的Activity信息

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对象

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

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

public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
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")) {
initializeJavaContextClassLoader();
}
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)) {
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)) {
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);
}
return app;
}

从这个方法中可以看到, 如果Application这个对象已经被创建过, 那么就不会再重复创建了, 这也就意味着一个应用只有一个Application对象的原因. Application对象的创建也是通过Instrumentation类来完成, 这个过程和Activity对象的创建是一致的, 都是通过类加载器来实现. Application创建完毕后, 系统会通过InstrumentationcallApplicationOnCreate()方法来调用Application#onCreate()方法.

4. 创建ContextImpl对象并通过Activity的attach方法来完成重要数据的初始化

Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
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);

ContextImpl是一个很重要的数据结构, 它是Context的具体实现, Context中的大部分逻辑都是由ContentImpl来完成的. ContextImpl是通过Activity的attach()方法来和Activity建立关联的,除此之外, 在attach()中Activity还会完成Window的创建并建立自己和Window的关联, 这样当Window接收到外部输入事件收就可以将事件传递给Activity.

5. 调用Activity的onCreate()方法

mInstrumentation.callActivityOnCreate(activity, r.state);, 由于Activity的onCreate()已经被调用, 这也意味着Activity已经完成整个启动过程.

Service的工作流程

Service的启动过程

同样从ContextImpl#startService()这个方法作为入口.

这个方法会调用startServiceCommon()并返回. 这个方法内部通过ActivityManagerNative.getDefault()获得一个AMS并调用startService()开启一个服务. 在这里通过AMS来启动一个服务的行为是属于远程调用的过程.

看一下startService()

public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, int userId) {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (DEBUG_SERVICE)
Slog.v(TAG, "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, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}

这段主要就是AMS通过mServices这个对象来完成Service后续的启动过程. 这里mService的对象类型是ActivityServices(这是一个辅助AMS进行Service管理的类, 包括Service的启动,绑定和停止等).

这里调用了mServices.startServiceLocked()然后这个方法最后又调用了startServiceInnerLocked(), 实现如下.

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
ServiceRecord r, boolean callerFg, boolean addToStarting) {
ProcessStats.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);
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, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
Slog.v(TAG, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStarts();
}
} else if (callerFg) {
smap.ensureNotStartingBackground(r);
}
return r.name;
}

ServiceRecord描述的是一个Service记录, ServiceRecord一直贯穿着整个Service的启动过程. startServiceInnerLocked()方法并没有完成具体的启动工作, 而是把后续的工作交给了bringUpServiceLocked(),在bringUpServiceLocked()又调用了realStartServiceLocked()方法. 这个方法算是真正的启动一个Service.

realStartServiceLocked()首先通过app.thread.scheduleCreateService()方法来创建Service对象并调用其onCreate(), 接着再通过sendServiceArgsLoceked()方法来调用Service的其他方法, 比如onStartCommond这两个过程均是进程间通信. app.thread是一个Binder对象. 具体实现看ApplicationThread即可. 在Activity启动流程的时候已经解释过了.

所以只查看ApplicationService的启动过程的处理即可. 这对应着它的scheduleCreateService().

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

这个过程和Activity类似, 都是通过H来完成. 最终处理消息接收结果会调用handleCreateService.

private void handleCreateService(CreateServiceData data) {
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) {
// nothing to do.
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}

handleCreateService做了如下事情

  1. 通过类加载器创建Service的实例
  2. 创建Application对象并调用其onCreate(), 当然Application创建过程只会有一次.
  3. 接着创建ContextImpl对象并通过Service的attach方法建立二者之间的关系, 这个过程和Activity实际上是类似的. 毕竟Service和Activity都是一个Context.
  4. 调用onCreate()并将Service对象存储到ActivityThread中的一个列表. 就是final ArrayMap<IBinder, Service> mServices = new ArrayMap<IBinder, Service>();

onCreate()方法被执行了也就意味着Service已经启动了. 除此之外, ActivityThread中还会通过handleServiceArgs()方法调用Service的onStartCommand()方法.

Service的绑定过程

和启动过程一样, 绑定过程同样是从ContextImpl开始的. 先查看bindServiceCommon().

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), 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();
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
return false;
}
}

这段代码首先将客户端的ServiceConnection对象转化成为ServiceDispatcher.InnerConnection对象. 不能直接使用ServiceConnection对象必须借助于Binder才能让远程服务回调自己的方法. 而ServiceDispatcher的内部类InnerConnection刚好充当了Binder这个角色.

ServiceDispatcher的作用就是连接ServiceConnectionInnerConnection的作用. 这个过程由LoadedApkgetServiceDispatcher()方法完成. 实现如下:

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) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}

mService是一个ArrayMap, 它存储了一个应用当前活动的ServiceConnectionServiceDispatcher的映射关系.

系统首先会查找是否存在相同的ServiceConnection, 如果不存在就会重新创建一个ServiceDispatch对象并将其存储在mService中, 其中的key是ServiceConnection,value是ServiceDispatcher, 在ServiceDispatcher的内部又保存了ServiceConnectionInnerConnection对象. 当Service和客户端建立连接后, 系统会通过InnerConnection来调用ServiceConnection中的onServiceConnected()方法. 这个过程可能是跨进程的. 当ServiceDispatcher创建好了以后, getServiceDispatcher会返回其保存的InnerConnection对象.

接着bindServiceCommon方法会通过AMS完成Service的具体绑定, 这对应着AMS#bindService()方法.

public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType,
connection, flags, userId);
}
}

然后AMS会调用ActivityService#bindServiceLocked()方法. 然后调用bringUpServiceLocked(), 继续调用. 发现调到了realStartServiceLocked. 这里面的逻辑和启动过程类似. 最终都是通过ApplicationThread来完成Service实例的创建并执行其onCreate()方法. 这里不再重复说明.

与Service启动稍微不同的是:

  • 绑定过程: 会调用到app.thread(ActivityThread)scheduleBindService()方法. 而这个过程的实现是在ActiveService#requestServiceBindingLocked()方法.
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean execInFg, boolean rebind) {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
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);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (RemoteException e) {
if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
return false;
}
}
return true;
}

app.thread实际上就是ApplicationThread. ApplicationThread的一系列以schedule开头的方法, 其内部都是通过Handler H来中转的.

H的内部 接收到BIND_SERVICE消息需要处理时, 会交给ActivityThread#handleBindService(). 在handlerBindService中, 首先根据Service的token取出Service对象. 然后调用Service#onBind()方法, Service的onBinder方法返回一个Binder对象给客户端使用. 原则上来说, Service#onBind()方法被调用后, Service就处于绑定状态, 但是onBind方法是Service的方法, 这个时候客户端并不知道已经成功连接Service, 所以还必须调用客户端的ServiceConnection中的onServiceConnected(), 这个过程是由AMS#publishService()来完成.

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) {
}
} 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()方法只会执行一次, 除非Service被终止了. 当Service的onBind()执行之后, 系统还需要告知客户端已经成功连接Service了. 这些过程是在AMS#publishService()实现.

public void publishService(IBinder token, Intent intent, IBinder service) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}

可以看到这里将具体的工作交给了mServices.publishServiceLocked()它是一个ActiveService类型. 其核心代码就是:

c.conn.connected(r.name, service);
//c的类型是ConnectionRecord
//c.conn的类型是ServiceDispatcher.InnerConnection
//service参数就是Service的onBind返回的Binder对象

InnerConnection#connected()方法内又调用ServiceDispatcher的connected()内部就是创建一个RunConnection()发送到mActivityThread的消息中.

对于Service的绑定过程来说, ServiceDispatchermActivityThread是一个Handler, 就是ActivityThread#H, 从前面的ServiceDispatcher的创建过程来说, mActivityThread不会为null, 所以RunConnection就可以经由H的post方法从而运行在主线程. 因此客户端的ServiceConnection中的方法是在主线程被回调的.

RunConnection是一个Runnable接口, run()方法也是简单调用ServiceDispatcher#doConnected方法, 由于ServiceDispatcher内部保存了客户端的ServiceConnection对象, 因此他可以很方便调用ServiceConnection对象的onServiceConnected()


解绑和停止过程, 基本类似… 恩 书上这么说的.

BroadcastReceiver的工作流程

简单回顾一下广播的使用方法, 首先定义广播接收者, 只需要继承BroadcastReceiver并重写onReceive()方法即可. 定义好了广播接收者, 还需要注册广播接收者, 分为两种静态注册或者动态注册. 注册完成之后就可以发送广播了.

广播的注册过程

广播的注册有两种静态注册, 动态注册. 其中静态注册的广播在应用安装时由系统自动完成注册, 具体来说是有PMS(PackageManagerService)来完成整个注册过程的. 除了广播外, 其他三大组件也都是在应用安装时由PMS解析并注册的.

动态注册的过程是从ContextWrapper#registerReceiver()开始的. 和Activity或者Service一样. ContextWrapper并没有做实际的工作, 而是将注册的过程直接交给了ContextImpl来完成.

ContextImpl#registerReceiver()方法调用了本类的registerReceiverInternal()方法.

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 {
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}

上述代码中, 系统首先从mPackageInfo获取到IIntentReceiver对象, 然后再采用跨进程的方式向AMS发送广播注册的请求. 之所以采用IIntentReceiver而不是直接采用BroadcastReceiver, 这是因为上述注册过程中是一个进程间通信的过程. 而BroadcastReceiver作为Android中的一个组件是不能直接跨进程传递的. 所有需要通过IIntentReceiver来中转一下.

IIntentReceiver作为一个Binder接口, 它的具体实现是LoadedApk.ReceiverDispatcher.InnerReceiver, ReceiverDispatcher的内部同时保存了BroadcastReceiverInnerReceiver, 这样当接收到广播的时候, ReceiverDispatcher可以很方便的调用BroadcastReceiver#onReceive()方法. 这里和Service很像有同样的类, 并且内部类中同样也是一个Binder接口.

看一下LoadedApk.ReceiverDispatcher#getIIntentReceiver()的实现, 很显然getReceiverDispatcher()重新创建了一个ReceiverDispatcher对象并将其保存的InnerReceiver对象作为返回值返回, 其中InnerReceiver对象和BroadcastReceiver都是在ReceiverDispatcher的构造方法中被保存起来的.

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()方法, 这里只关心里面的核心部分. 这段代码最终会把远程的InnerReceiver对象以及IntentFilter对象存储起来, 这样整个广播的注册就完成了.

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
//...
mRegisteredReceivers.put(receiver.asBinder(), rl);
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,permission, callingUid, userId);
rl.add(bf);
mReceiverResolver.addFilter(bf);
}

广播的发送和接收过程

当通过send()发送广播时, AMS会查找出匹配的广播接收者并将广播发送给他们处理. 广播的发送种类有: 普通广播, 有序广播, 粘性广播. 这里分析普通广播.

广播的发送和接收, 本质就是一个过程的两个阶段. 广播的发送仍然开始于ContextImpl#sendBroadcase()方法, 之所以不是Context, 那是因为Context#sendBroad()是一个抽象方法. 和广播的注册过程一样, ContextWrapper#sendBroadcast()仍然什么都不做, 只是把事情交给了ContextImpl去处理, ContextImpl#sendBroadcast()源码如下

@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
}

看到ContextImpl里面也几乎什么都没有做, 内部直接向AMS发起了一个异步请求用于发送广播. 接下来看AMS#broadcastIntent()方法.

public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle options,
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, null, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}

看到这里, 又继续调用broadcastIntentLocked()方法, 这个方法有点长. 在代码开始处

// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

这个表示默认情况下广播不会发送给已经停止的应用, android5.0中. 而android 3.1开始就增添了两个标记为. 分别是FLAG_INCLUDE_STOPPED_PACKAGES, FLAG_EXCLUDE_STOPPED_PACKAGES. 用来控制广播是否要对处于停止的应用起作用.

  • FLAG_INCLUDE_STOPPED_PACKAGES: 包含停止应用, 广播会发送给已停止的应用.
  • FLAG_EXCLUDE_STOPPED_PACKAGES: 不包含已停止应用, 广播不会发送给已停止的应用

android 3.1开始, 系统就为所有广播默认添加了FLAG_EXCLUDE_STOPPED_PACKAGES标识, 为了防止广播无意间或者不必要的时候调起已经停止运行的应用. 当这两个标记共存的时候以FLAG_INCLUDE_STOPPED_PACKAGES(非默认项为主).


应用处于停止分为两种

  1. 应用安装后未运行
  2. 被手动或者其他应用强停

开机广播同样受到了这个标志位的影响. 从Android 3.1开始处于停止状态的应用同样无法接受到开机广播, 而在android 3.1之前处于停止的状态也是可以接收到的开机广播的.

broadcastIntentLocked()内部, 会根据intent-filter查找出匹配的广播接收者并经过一系列的条件过滤. 最终会将满足条件的广播接收者添加到BroadcastQueue中, 接着BroadcastQueue就会将广播发送给相应广播接收者.

if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
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);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
+ ": prev had " + queue.mOrderedBroadcasts.size());
if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
"Enqueueing broadcast " + r.intent.getAction());
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}

跟进BroadcastQueue#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类型的消息, BroadcastQueue收到消息后会调用processNextBroadcast()方法. 这个方法对普通广播的处理如下:

// First, deliver any non-serialized broadcasts right away.
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);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}

无序广播存储在mParallelBroadcasts中, 系统会遍历这个集合并将其中的广播发送给他们所有的接收者, 具体的发送过程是通过deliverToRegisteredReceiverLocked()方法实现. deliverToRegisteredReceiverLocked()负责将一个广播发送给一个特定的接收者, 它的内部调用了performReceiverLocked方法来完成具体发送过程.

performReceiverLocked()方法实现如下, 由于接收广播会调起应用程序, 因为app.thread不为null, 根据前面的总结app.thread仍然指ApplicationThread.

private static 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.
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} 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);
}
}

而调用的ApplicationThread#scheduleRegisteredReceiver()实现比较简单, 它通过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);
}

上面的receiver.performReceive()中的receiver对应着IIntentReceiver类型的接口. 而具体的实现就是ReceiverDispatcher$InnerReceiver. 这两个嵌套的内部类是所属在LoadedApk中的. 好了看一下performReceiver()

public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
+ " to " + (rd != null ? rd.mReceiver : null));
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
// The activity manager dispatched a broadcast to a registered
// receiver in this process, but before it could be delivered the
// receiver was unregistered. Acknowledge the broadcast on its
// behalf so that the system's broadcast sequence can continue.
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
}
}
}

上面又调用了LoadedApk$ReceiverDispatcher#performReceive()的方法.

public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
+ " to " + mReceiver);
}
Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (!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);
}
}
}

performReceiver()这个方法中, 会创建一个Args对象并通过mActivityThreadpost方法执行args中的逻辑. 而这些类的本质关系就是:

  • Args: 实现类Runnable
  • mActivityThread: 是一个Handler, 就是ActivityThread中的mH. mH就是ActivityThread$H. 这个内部类H以前说过.

而实现Runnable接口的Args中有如下代码:

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

这个时候BroadcastReceiver#onReceive()方法被执行了, 也就是说应用已经接收到了广播, 同时onReceive()方法是在广播接收者的主线程中被调用的.

ContentProvider的工作机制

ContentProvider是一种内容共享型组件, 它通过Binder向其他组件乃至其他应用提供数据. 当ContentProvider所在的进程启动时, ContentProvider会同时启动并发布到AMS中. 要注意:这个时候ContentProvider的onCreate()方法是先于Application的onCreate()执行的这一点在四大组件是少有的现象.

当一个应用启动的时候, 入口的方法为ActivityThread#main()方法, main方法为一个静态方法, 在main方法中会创建ActivityThread的实例, 并创建主线程的消息队列, 然后在ActivityThread#attach()方法中会远程调用AMS#attachApplication()并将ApplicationThread对象提供给AMS.

ApplicationThread是一个Binder对象, 它的Binder接口是IApplicationThread, 主要用于ActivityThreadAMS之间的通信, 这一点在前面多次提到. 在AMSattachApplication()中, 会调用ApplicationThread#bindApplication(). 这个过程同样是跨进程的. bindApplication()中会经过 ActivityThread中的mh(Handler) 切换到ActivityThread中去执行, 具体的方式是handleBindApplication().

handleBindApplication()方法中, ActivityThread会创建Application对象并加载ContentProvider. 需要注意的是, ActivityThread会先加载ContentProvider, 然后在调用Application#onCreate()方法


以上就是ContentProvider的启动过程, ContentProvider启动后, 外界就可以通过它所提供的增删改查这四个接口来操作ContentProvider中的数据源, 这四个方法都是通过Binder来调用的, 外界无法直接访问ContentProvider, 它只能通过AMS根据URI来获取到对应的ContentProviderBinder接口IContentProvider, 然后再通过IContentProvider来访问ContentProvider中的数据源.

ContentProvider是否属于单实例?

具体ContentProvider是否是单实例取决于android:multiprocess属性来决定的, 当其值为false的时候, 就是单实例也是默认值. 如果为true那就为多实例. 这个时候在每一个调用者的进程中都会存在一个ContentProvider对象.


通过单实例的ContentProvider来分析一下启动过程

首先访问ContentProvider需要通过ContentResolver, ContentResolver是一个抽象类, 通过Content#getContentResolver()方法获取的实际上是ApplicationContentResolver对象, 而这个类继承了ContentProvider并实现了其抽象方法. 当ContentProvider所在的进程未启动时, 第一次访问它的时候就会触发ContentProvider的创建, 当然这也伴随着ContentProvider所在的进程的启动. 通过四个对数据的操作方法中的任何一个, 都可以触发ContentProvider的启动过程.

四种操作过程差不多, 那么这里以query方法为例

首先会获取IContentProvider对象, 不管是通过acquireUnstableProvider()方法还是直接通过acquireProvider()方法, 他们的本质都是一样的, 最终都是通过acquireProvider方法来获取ContentProvider.

ApplicationContentResolver#acquireProvider()方法并没有处理任何逻辑, 它直接调用了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;
}
IActivityManager.ContentProviderHolder holder = null;
try {
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable);
} catch (RemoteException ex) {
}
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对象, 这个集合的存储类型ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap. 如果目前ContentProvider没有启动, 那么就发送一个进程间请求给AMS让其启动项目目标ContentProvider, 最后再通过installProvider()方法来修改引用计数.

那么AMS是如何启动ContentProvider的呢?

关于ContentProvider被启动的时候会伴随着进程的启动, 在AMS中, 首先会启动ContentProvider所在的进程, 然后再启动ContentProvider. 启动进程是由AMS#startProcessLocked()方法来完成, 其内部主要是通过Process#start()方法来完成一个新进程的启动, 新进程启动后其入口方法为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());
AndroidKeyStoreProvider.install();
// 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");
}

ActivityThread#main()是一个静态方法, 在它的内部首先会创建ActivityThread实例并调用attach()方法来进行一系列初始化, 接着就开始进行消息循环. ActivityThread#attach()方法会将Application对象通过AMS#attachApplication方法跨进程传递给AMS, 最终AMS会完成ContentProvider的创建过程.

ActivityThread#attach()部分代码:

try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}

AMS#attachApplication()方法调用了attachApplication(), 然后又调用了ApplicationThread#bindApplication(), 这个过程也属于进程通信.

而上面的bindApplication()方法会发送一个BIND_APPLICATION类型的消息给mH, 这是一个Handler, 它收到消息后会调用ActivityThread#handleBindApplication()方法. bindApplication()发送源码如下:

AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);

ActivityThread#handlerBindApplication()则完成了Application的创建以及ContentProvider 可以分为如下四个步骤:

  1. 创建ContentProviderInstrumentation
  2. 创建Application对象
  3. 启动当前进程的ContentProvider并调用onCreate()方法. 主要内部实现是installContentProvider()完成了ContentProvider的启动工作, 首先会遍历当前进程的ProviderInfo的列表并一一调用installProvider()方法来启动他们, 接着将已经启动的ContentProvider发布到AMS中, AMS会把他们存储在ProviderMap中, 这样一来外部调用者就可以直接从AMS中获取到ContentProvider. installProvider()内部通过类加载器创建的ContentProvider实例并在方法中调用了attachInfo(), 在这内部调用了ContentProvider#onCreate()
  4. 调用Application#onCreate()

经过了上述的四个步骤, ContentProvider已经启动成功, 并且其所在的进程的Application也已经成功, 这意味着ContentProvider所在的进程已经完成了整个的启动过程, 然后其他应用就可以通过AMS来访问这个ContentProvider了.

当拿到了ContentProvider以后, 就可以通过它所提供的接口方法来访问它. 这里要注意: 这里的ContentProvider并不是原始的ContentProvider. 而是ContentProvider的Binder类型对象IContentProvider, 而IContentProvider的具体实现是ContentProviderNativeContentProvider.Transport. 后者继承了前者.

如果还用query方法来解释流程: 那么最开始其他应用通过AMS获取到ContentProviderBinder对象就是IContentProvider. 而IContentProvider的实际实现者是ContentProvider.Transport. 因此实际上外部应用调用的时候本质上会以进程间通信的方式调用ContentProvider.Transport的query()方法

下一章: 第10章 Android的消息机制