Android系统中的四大组件是构成Android应用程序的基础。包括Activity、Service、BroadcastReceiver、ContentProvider。Android开发中无时无刻不在使用这四大组件。因此了解它们的工作过程能让我们对四大组件的理解更加深刻,同时对Android系统的认识更加清晰。
Activity启动过长由于包含应用程序启动的过长,内容篇幅过长,进行了拆分。Activity启动过程请查看这篇,Activity启动过程。
启动Service,我们会调用startService方法,这里会调用mBase的startService方法,这里的mBase对象指的是ContextImpl。
源码路径:frameworks\base\core\java\android\content\ContextWrapper.java
Context mBase;
@Override
public @Nullable ComponentName startService(Intent service) {
return mBase.startService(service);
}
startService方法调用startServiceCommon方法,然后调用ActivityManagerService类的startService方法。
源码路径:frameworks\base\core\java\android\app\ContextImpl.java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
//AMS的startService方法
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), getAttributionTag(), 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());
} else if (cn.getPackageName().equals("?")) {
throw ServiceStartNotAllowedException.newInstance(requireForeground,
"Not allowed to start service " + service + ": " + cn.getClassName());
}
}
// If we started a foreground service in the same package, remember the stack trace.
if (cn != null && requireForeground) {
if (cn.getPackageName().equals(getOpPackageName())) {
Service.setStartForegroundServiceStackTrace(cn.getClassName(),
new StackTrace("Last startServiceCommon() call for this service was "
+ "made here"));
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
startService方法中,mServices类型为ActiveServices,调用startServiceLocked方法。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
final ActiveServices mServices;
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage,
String callingFeatureId, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, callingFeatureId, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
startServiceLocked方法重载,retrieveServiceLocked方法会查找是否由于参数service对应的ServiceRecord,如果没找到,就会调用PackageManagerService去获取参数service对应的Service信息,并封装到ServiceRecord,最后将ServiceLookupResult返回。ServiceRecord用于描述一个Service,和之前的ActivityRecord类似。获取到ServiceRecord后,传入到startServiceInnerLocked方法中,然后又调用bringUpServiceLocked方法,获取进程名processName,然后将processName和Service的uid传入getProcessRecordLocked方法中,查询是否存在一个与Service对应的ProcessRecord类型的app,ProcessRecord主要描述运行Service的应用程序进程信息,如果Service对应的app为空,则调用ActivityManagerService类的startProcessLocked方法来创建应用程序进程。这里和前面应用程序启动创建应用程序进程实现一致。如果Service对应的app不为空,则通过realStartServiceLocked方法启动Service,realStartServiceLocked方法中调用thread的scheduleCreateService方法,这里的thread是前面传递的ApplicationThread,ApplicationThread是ActivityThread的内部类。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
@Nullable String callingFeatureId, final int userId)
throws TransactionTooLargeException {
return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
callingPackage, callingFeatureId, userId, false, null);
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired,
String callingPackage, @Nullable String callingFeatureId, final int userId,
boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken)
throws TransactionTooLargeException {
...
ServiceLookupResult res =
retrieveServiceLocked(service, null, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
ServiceRecord r = res.record;
...
final ComponentName realResult =
startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg,
allowBackgroundActivityStarts, backgroundActivityStartsToken);
}
private ServiceLookupResult retrieveServiceLocked(Intent service,
String instanceName, String resolvedType, String callingPackage,
int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
boolean allowInstant) {
return retrieveServiceLocked(service, instanceName, false, 0, null, resolvedType,
callingPackage, callingPid, callingUid, userId, createIfNeeded, callingFromFg,
isBindExternal, allowInstant);
private ServiceLookupResult retrieveServiceLocked(Intent service,
String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
String sdkSandboxClientAppPackage, String resolvedType,
String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
boolean allowInstant) {
ServiceRecord r = null;
...
r = new ServiceRecord(mAm, className, name, definingPackageName,
definingUid, filter, sInfo, callingFromFg, res,
sdkSandboxProcessName, sdkSandboxClientAppUid,
sdkSandboxClientAppPackage);
res.setService(r);
...
return new ServiceLookupResult(r, resolution.getAlias());
}
private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
int callingUid, int callingPid, boolean fgRequired, boolean callerFg,
boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken)
throws TransactionTooLargeException {
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
callingUid, wasStartRequested);
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting, int callingUid, boolean wasStartRequested)
throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
false /* whileRestarting */,
false /* permissionsReviewRequired */,
false /* packageFrozen */,
true /* enqueueOomAdj */);
}
final ActivityManagerService mAm;
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj)
throws TransactionTooLargeException {
//Service 进程
final String procName = r.processName;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
//Service进程存在
if (app != null) {
//ApplicationThread
final IApplicationThread thread = app.getThread();
final int pid = app.getPid();
final UidRecord uidRecord = app.getUidRecord();
if (thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode,
mAm.mProcessStats);
//启动Service
realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
enqueueOomAdj);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
}
}
//应用进程不存在
if (app == null && !permissionsReviewRequired && !packageFrozen) {
...
//创建应用程序进程
app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated
//mPendingServices:要求启动但尚未启动的服务列表
mPendingServices.add(r);
}
}
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
boolean enqueueOomAdj) throws RemoteException {
...
thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.mState.getReportedProcState());
}
我们先分析应用程序进程不存在的情况,前面应用程序启动中我们清楚,进程创建完成后会反射动态调用ActivityThread的main方法,接着会调用AMS的attachApplication方法,然后调用attachApplicationLocked方法,attachApplicationLocked方法中会调用ActiveServices类的attachApplicationLocked方法
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
final ActiveServices mServices;
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
//调用ActivityService的attachApplicationLocked方法
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
ActiveServices类的attachApplicationLocked方法中会遍历mPendingServices,然后调用realStartServiceLocked启动Service,这就和上面启动Service接轨了,现在进程存在。
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (proc != sr.isolationHostProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
final IApplicationThread thread = proc.getThread();
final int pid = proc.getPid();
final UidRecord uidRecord = proc.getUidRecord();
mPendingServices.remove(i);
i--;
proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,
mAm.mProcessStats);
realStartServiceLocked(sr, proc, thread, pid, uidRecord, sr.createdFromFg,
}
继续分析进程存在的情况,进入到ActivityThread类中,scheduleCreateService方法中将Service启动参数封装成一个CreateServiceData对象,然后发送了一条CREATE_SERVICE的消息,并将CreateServiceData传递,看下Handler是怎么处理CREATE_SERVICE消息,调用handleCreateService方法,最终在handleCreateService方法中,根据CreateServiceData创建Service实例,通过Service的attach方法初始化Service,然后调用Service的onCreate方法,这样Service就被启动了。
源码路径:frameworks\base\core\java\android\app\ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
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);
}
}
class H extends Handler {
public void handleMessage(Message msg) {
case CREATE_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceCreate: " + String.valueOf(msg.obj)));
}
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
private void handleCreateService(CreateServiceData data) {
Service service = null;
//缓存读取Application,不存在创建Application
Application app = packageInfo.makeApplicationInner(false, mInstrumentation);
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
//上下文
ContextImpl context = ContextImpl.getImpl(service
.createServiceBaseContext(this, packageInfo));
context.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
//初始化Service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServicesData.put(data.token, data);
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
...
}
除了通过startService方法来启动Service,还可以通过bindService方法来绑定Service,接下来看下Service的绑定过程。
mBase我们知道类型为ContextImpl对象,bindServiceCommon方法中将ServiceConnection转换为IServiceConnection,实现在LoadedApk中,其中executor为null,handler为主线程也就是ActivityThread中我们经常提到的H类。最终调用AMS的bindServiceInstance方法。
源码路径:
frameworks\base\core\java\android\content\ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
@Override
public boolean bindService(Intent service, int flags, Executor executor,
ServiceConnection conn) {
return mBase.bindService(service, flags, executor, conn);
}
源码路径:frameworks\base\core\java\android\app\ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
getUser());
}
final @NonNull ActivityThread mMainThread;
final @NonNull LoadedApk mPackageInfo;
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
...
IServiceConnection sd;
if (mPackageInfo != null) {
//executor为null
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
}
int res = ActivityManager.getService().bindServiceInstance(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
}
AMS中bindServiceInstance方法重载调用ActiveServices类的bindServiceLocked方法。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
final ActiveServices mServices;
public int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String instanceName,
String callingPackage, int userId) throws TransactionTooLargeException {
return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
instanceName, false, 0, null, callingPackage, userId);
}
private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String instanceName,
boolean isSdkSandboxService, int sdkSandboxClientAppUid,
String sdkSandboxClientAppPackage, String callingPackage, int userId)
throws TransactionTooLargeException {
...
synchronized (this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
sdkSandboxClientAppPackage, callingPackage, userId);
}
}
在bindServiceLocked方法中,构造出ServiceLookupResult,然后调用ServiceRecord类的retrieveAppBindingLocked方法生成AppBindRecord对象,应用程序进程通过Intent绑定Service时,通过AppBindRecord来维护Service与应用程序之间的关联,其内部存储了ServiceRecord、ProcessRecord、绑定Service Intent的IntentBindRecord和绑定通信记录信息的ArraySet<ConnectionRecord>
,创建了一个ConnectionRecord对象,它是用于描述应用程序进程和Service建立的一次通信。
然后调用bringUpServiceLocked方法启动Service,具体启动细节在Service启动过程已经说明,接着判断Service是否在运行并且接收到绑定Service返回的Binder,这样应用程序进程就可以通过Binder来获取要绑定的Service访问接口,c.conn的对象为IServiceConnection,具体实现在ServiceDispatcher.InnerConnection
,前面有提到,其中ServiceDispatcher为LoadApk的内部类,后面会分析到。
如果当前应用程序进程是第一个与Service进行绑定并且Service调用过onUnBind方法,则调用requestServiceBindingLocked方法,如果应用程序进程没有发送过绑定Service的请求,也会调用requestServiceBindingLocked方法,区别在于最后一个参数,它表示不是重新绑定,当前我们还没有绑定Service呢,requestServiceBindingLocked方法中,我们没有绑定过Service并且是第一个与Service进行绑定,r.app类型为ProcessRecord对象,getThread方法获取的是IApplicationThread,它的实现在ActivityThread类中,继续分析scheduleBindService方法的实现。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
String sdkSandboxClientAppPackage, String callingPackage, final int userId)
throws TransactionTooLargeException {
...
ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
isBindExternal, allowInstant);
ServiceRecord s = res.record;
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage, res.aliasComponent);
IBinder binder = connection.asBinder();
s.addConnection(binder, c);
b.connections.add(c);
if (activity != null) {
activity.addConnection(c);
}
//启动Service
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired, packageFrozen, true) != null) {
mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
return 0;
}
//Service在运行 && 接收到绑定Service返回的Binder, b.intent.received=false
if (s.app != null && b.intent.received) {
final ComponentName clientSideComponentName =
res.aliasComponent != null ? res.aliasComponent : s.name;
try {
// c.conn->IServiceConnection
c.conn.connected(clientSideComponentName, b.intent.binder, false);
//第一个与Service进行绑定并已经调用过onUnBind方法,b.intent.doRebind=false
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
//没有发送过绑定service的请求
}else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false)
...
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
//i.requested=false;i.apps.size()=1
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind",
OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.mState.getReportedProcState());
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
...
return true;
}
源码路径:
frameworks\base\services\core\java\com\android\server\am\ServiceRecord.java
public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord i = bindings.get(filter);
if (i == null) {
i = new IntentBindRecord(this, filter);
bindings.put(filter, i);
}
AppBindRecord a = i.apps.get(app);
if (a != null) {
return a;
}
a = new AppBindRecord(this, i, app);
i.apps.put(app, a);
return a;
}
源码路径:
frameworks\base\services\core\java\com\android\server\am\AppBindRecord.java
final class AppBindRecord {
final ServiceRecord service; // The running service.
final IntentBindRecord intent; // The intent we are bound to.
final ProcessRecord client; // Who has started/bound the service.
final ArraySet<ConnectionRecord> connections = new ArraySet<>();
AppBindRecord(ServiceRecord _service, IntentBindRecord _intent,
ProcessRecord _client) {
service = _service;
intent = _intent;
client = _client;
}
}
源码路径:
frameworks\base\services\core\java\com\android\server\am\IntentBindRecord.java
final class IntentBindRecord {
/** The running service. */
final ServiceRecord service;
/** The intent that is bound.*/
final Intent.FilterComparison intent; //
/** All apps that have bound to this Intent. */
final ArrayMap<ProcessRecord, AppBindRecord> apps
= new ArrayMap<ProcessRecord, AppBindRecord>();
/** Binder published from service. */
IBinder binder;
/** Set when we have initiated a request for this binder. */
boolean requested;
/** Set when we have received the requested binder. */
boolean received;
/** Set when we still need to tell the service all clients are unbound. */
boolean hasBound;
/** Set when the service's onUnbind() has asked to be told about new clients. */
boolean doRebind;
String stringName;
IntentBindRecord(ServiceRecord _service, Intent.FilterComparison _intent) {
service = _service;
intent = _intent;
}
}
源码路径:
frameworks\base\services\core\java\com\android\server\am\ProcessRecord.java
IApplicationThread getThread() {
return mThread;
}
scheduleBindService方法中发送一条BIND_SERVICE消息,处理消息调用handleBindService方法,首先获取要绑定的Service,然后判断是否重新绑定,不是重新绑定则调用Service的onBind生命周期方法,重新绑定则会调用Service的onRebind生命周期方法,完成重新绑定。onBind生命周期方法调用后,又调用了AMS的publishService方法
源码路径:frameworks\base\core\java\android\app\ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
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);
}
}
class H extends Handler {
public void handleMessage(Message msg) {
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
case UNBIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
handleUnbindService((BindServiceData)msg.obj);
schedulePurgeIdler();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
s.getAttributionSource());
try
//是否重新绑定
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
...
}
publishService方法中调用ActiveServices的publishServiceLocked方法。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
final ActiveServices mServices;
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);
}
}
最终调用到LoadApk类中内部类ServiceDispatcher的connect方法。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
final ComponentName clientSideComponentName =
c.aliasComponent != null ? c.aliasComponent : r.name;
try {
c.conn.connected(clientSideComponentName, service, false);
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false);
}
在前面ContextImpl中将ServiceConnection转换为IServiceConnection时,传递的参数是ActivityThread的handler H对象,也就是现在的mActivityThread,发送了一个消息,在RunConnection的run方法中可以知道,调用doConnecteda方法,最终会回调ServiceConnection的onServiceConnected方法,Service 绑定和连接完成。
源码路径:frameworks\base\core\java\android\app\LoadedApk.java
static final class ServiceDispatcher {
private final Handler mActivityThread;
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityExecutor != null) {
mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
} else if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
...
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
} else {
// If there is a new viable service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
}
}
了解广播的静态注册需要了解PackageManagerService,后面会对系统服务拆分分析PackageManagerService时再分析广播的静态注册过程。
动态注册广播,需要调用registerReceiver方法,它在ContextWrapper中实现。mBase就不用再说了,它是ContextImpl对象。
@Override
public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
registerReceiver方法重载,最终调用registerReceiverInternal方法,scheduler为null,则获取ActivityThread类的Handler。rd是
IIntentReceiver类型,它是一个Binder接口,用于广播的跨进程通信,它的实现在LoadedApk.ReceiverDispatcher.InnerReceiver中。接着调用AMS的registerReceiverWithFeature方法。
源码路径:frameworks\base\core\java\android\app\ContextImpl.java
final @NonNull ActivityThread mMainThread;
final @NonNull LoadedApk mPackageInfo;
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
//ActivityThread.H类
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 {
ActivityThread thread = ActivityThread.currentActivityThread();
Instrumentation instrumentation = thread.getInstrumentation();
if (instrumentation.isInstrumenting()
&& ((flags & Context.RECEIVER_NOT_EXPORTED) == 0)) {
flags = flags | Context.RECEIVER_EXPORTED;
}
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(),
AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId,
flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
getAttributionSource());
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
registerReceiverWithFeature方法中通过getRecordForAppLOSP方法获取ProcessRecord对象,它是描述请求AMS注册广播接收者的Activity所在的应用程序进程,然后根据传入的IntentFilter类型filter得到actions列表,根据actions和userIds得到所有粘性广播的intent,然后传入到stickyIntents中,接下来从stickyIntents中找到匹配传入的参数filter的粘性广播的intent,将intent存入allSticky中。
继续向下分析,获取ReceiverList,如果为null则重新创建,它是用来存储广播接收者,接下来创建了BroadcastFilter对象,传入ReceiverList对象,它用来描述注册的广播接收者,它也被存储在ReceiverList中,mReceiverResolver是一个IntentResolver对象,BroadcastFilter被添加到mReceiverResolver中,这样AMS接收到广播就可以从mReceiverResolver中找到对应的广播接收者了,动态注册广播完成。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, String receiverId, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId, int flags)
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
synchronized(this) {
if (caller != null) {
callerApp = getRecordForAppLOSP(caller);
callingUid = callerApp.info.uid;
callingPid = callerApp.getPid();
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
instantApp = isInstantApp(callerApp, callerPackage, callingUid);
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();
}
boolean onlyProtectedBroadcasts = true;
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);
}
}
}
if (onlyProtectedBroadcasts) {
try {
onlyProtectedBroadcasts &=
AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
onlyProtectedBroadcasts = false;
Slog.w(TAG, "Remote exception", e);
}
}
}
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
//遍历寻找匹配的粘性广播
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
allSticky.add(intent);
}
}
}
synchronized (this) {
IApplicationThread thread;
if (callerApp != null && ((thread = callerApp.getThread()) == null
|| thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
final int totalReceiversForApp = rl.app.mReceivers.numberOfReceivers();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "
+ rl.pid + ", callerPackage: " + callerPackage);
}
rl.app.mReceivers.addReceiver(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
receiverId, permission, callingUid, userId, instantApp, visibleToInstantApps,
exported);
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
+ ", callerPackage is " + callerPackage);
} else {
//存储在ReceiverList
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
mReceiverResolver.addFilter(getPackageManagerInternal().snapshot(), 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, null, -1, -1, false, null, null, null, null, OP_NONE, null,
receivers, null, 0, null, null, false, true, true, -1, false, null,
false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {
...
}
广播分为多种类型,包括标准广播(无序广播)、有序广播、粘性广播(已废弃)等,我们分别进行分析。
发送标准广播(无序广播),需要调用sendBroadcast()方法,实现在ContextImpl类中,最终调用AMS的broadcastIntentWithFeature方法。
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
null, AppOpsManager.OP_NONE, null, false, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
首先验证广播是否合法,然后调用broadcastIntentLocked方法,其中有大量的action判断,针对静态注册的广播(开机,网络等待)处理发送。接着将动态注册的广播接收者和静态注册的广播接收者按照优先级高低不同存储在不同的列表中,再将这两个列表合并到receivers中,receivers中包含所有的广播接收者,创建BroadcastRecord对象将receivers传入,调用BroadcastQueue类的scheduleBroadcastsLocked方法。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
@Override
public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, String[] excludedPermissions,
String[] excludedPackages, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
//验证广播是否合法
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLOSP(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
return broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, excludedPermissions, excludedPackages, appOp, bOptions,
serialized, sticky, callingPid, callingUid, callingUid, callingPid, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
final Intent verifyBroadcastLocked(Intent intent) {
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
int flags = intent.getFlags();
if (!mProcessesReady) {
//启动检查时只接受动态注册的广播接收者-FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
}
//动态注册的广播接收者-FLAG_RECEIVER_REGISTERED_ONLY
else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
+ " before boot completion");
throw new IllegalStateException("Cannot broadcast before boot completed");
}
}
return intent;
}
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, String callerFeatureId, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, String[] excludedPermissions,
String[] excludedPackages, int appOp, Bundle bOptions, boolean ordered,
boolean sticky, int callingPid,
int callingUid, int realCallingUid, int realCallingPid, int userId) {
return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
excludedPermissions, excludedPackages, appOp, bOptions, ordered, sticky, callingPid,
callingUid, realCallingUid, realCallingPid, userId,
false /* allowBackgroundActivityStarts */,
null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastAllowList */);
}
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
@Nullable String callerFeatureId, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions,
String[] excludedPermissions, String[] excludedPackages, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid,
int realCallingUid, int realCallingPid, int userId,
boolean allowBackgroundActivityStarts,
@Nullable IBinder backgroundActivityStartsToken,
@Nullable int[] broadcastAllowList) {
final String action = intent.getAction();
...
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
receivers, resultTo, resultCode, resultData, resultExtras,
ordered, sticky, false, userId, allowBackgroundActivityStarts,
backgroundActivityStartsToken, timeoutExempt);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
final BroadcastRecord oldRecord =
replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
if (oldRecord != null) {
if (oldRecord.resultTo != null) {
final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
try {
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
false, false, oldRecord.userId, oldRecord.callingUid, callingUid);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ queue.mQueueName + "] sending broadcast result of "
+ intent, e);
}
}
} else {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
} else {
if (intent.getComponent() == null && intent.getPackage() == null
&& (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
}
}
scheduleBroadcastsLocked方法中发送了一条BROADCAST_INTENT_MSG消息,看下是如何处理消息的,调用processNextBroadcast方法,在processNextBroadcastLocked方法中,遍历mParallelBroadcasts,它是用来存储标准广播,获取列表中存储的BroadcastRecord对象,将这些对象发送给对应的广播接收者,调用deliverToRegisteredReceiverLocked方法,其中做了检查广播发送者或广播接收者的权限,通过权限检查最终调用performReceiveLocked方法,如果广播接收者所在的应用程序进程存在并且在运行,则调用IApplicationThread的scheduleRegisteredReceiver方法,它的实现在ActivityThread的内部类ApplicationThread中。
源码路径:
frameworks\base\services\core\java\com\android\server\am\BroadcastQueue.java
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;
}
private final class BroadcastHandler extends Handler {
public BroadcastHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG ["
+ mQueueName + "]");
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
}
private void processNextBroadcast(boolean fromMsg) {
synchronized (mService) {
processNextBroadcastLocked(fromMsg, false);
}
}
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
BroadcastRecord r;
if (fromMsg) {
//已经处理了BROADCAST_INTENT_MSG消息
mBroadcastsScheduled = false;
}
while (mParallelBroadcasts.size() > 0) {
//获取标准广播
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchRealTime = SystemClock.elapsedRealtime();
r.dispatchClockTime = System.currentTimeMillis();
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
System.identityHashCode(r));
Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
System.identityHashCode(r));
}
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);
//发送给对应的广播接收者
deliverToRegisteredReceiverLocked(r,
(BroadcastFilter) target, false, i);
}
...
}
}
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
...
if (filter.receiverList.app != null && filter.receiverList.app.isInFullBackup()) {
// Skip delivery if full backup in progress
// If it's an ordered broadcast, we need to continue to the next receiver.
if (ordered) {
skipReceiverLocked(r);
}
} else {
r.receiverTime = SystemClock.uptimeMillis();
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
maybeScheduleTempAllowlistLocked(filter.owningUid, r, r.options);
maybeReportBroadcastDispatchedEventLocked(r, filter.owningUid);
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId,
filter.receiverList.uid, r.callingUid);
// parallel broadcasts are fire-and-forget, not bookended by a call to
// finishReceiverLocked(), so we manage their activity-start token here
if (filter.receiverList.app != null
&& r.allowBackgroundActivityStarts && !r.ordered) {
postActivityStartTokenRemoval(filter.receiverList.app, r);
}
}
}
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser,
int receiverUid, int callingUid) throws RemoteException {
if (app != null) {
final IApplicationThread thread = app.getThread();
if (thread != null) {
try {
thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser,
app.mState.getReportedProcState());
...
}
} 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);
}
}
scheduleRegisteredReceiver方法中调用了IIntentReceiver对象的performReceive方法,前面提到过它的实现在LoadApk类的内部类ReceiverDispatcher.InnerReceiver中。
源码路径:frameworks\base\core\java\android\app\ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
}
InnerReceiver继承IIntentReceiver.Stub,它是Binder通信的服务器端,IIntentReceiver则是Binder通信的客户端、InnerReceiver在本地的代理,它的实现就是InnerReceiver,performReceiver方法中又调用ReceiverDispatcher类的performReceiver方法,将广播的intent等信息封装成Args对象,然后调用Handler类型的mActivityThread发送一条消息,Handler就是ActivityThread 的Handler H 类,getRunnable中最终调用到BroadcastReceiver的onReceive方法,这样注册的广播接收者就接收到了广播并得到了intent。
源码路径:frameworks\base\core\java\android\app\LoadedApk.java
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
@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 (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 = ActivityManager.getService();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}
final Handler mActivityThread;
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.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
final class Args extends BroadcastReceiver.PendingResult {
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;
private boolean mRunCalled;
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, int sendingUser) {
super(resultCode, resultData, resultExtras,
mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
mCurIntent = intent;
mOrdered = ordered;
}
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
if (ActivityThread.DEBUG_BROADCAST) {
int seq = mCurIntent.getIntExtra("seq", -1);
}
final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
mCurIntent = null;
mDispatched = true;
mRunCalled = true;
if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
sendFinished(mgr);
}
return;
}
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
mContext.getAttributionSource());
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//onReceiver接收广播回调
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
sendFinished(mgr);
}
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
};
}
}
}
有序广播发送、接收流程几乎和标准广播相似。发送有序广播,通过sendOrderedBroadcast()方法,context对象是ContextImpl,broadcastIntentWithFeature方法的serialized就是用来判断是否是有序广播的,现在是有序广播,传入true,调用到BroadcastQueue类的processNextBroadcastLocked方法中,mParallelBroadcasts我们知道是保存标准广播的。
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
String[] receiverPermissions = receiverPermission == null ? null
: new String[] {receiverPermission};
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
null, Activity.RESULT_OK, null, null, receiverPermissions,
null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, true, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
BroadcastRecord为null,BroadcastDispatcher类的getNextBroadcastLocked方法获取BroadcastRecord,最终也会调用到deliverToRegisteredReceiverLocked方法,接下来其它的流程和标准广播一致。
源码路径:
frameworks\base\services\core\java\com\android\server\am\BroadcastQueue.java
final BroadcastDispatcher mDispatcher;
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
BroadcastRecord r;
do {
final long now = SystemClock.uptimeMillis();
r = mDispatcher.getNextBroadcastLocked(now);
...
} while (r == null)
...
final BroadcastOptions brOptions = r.options;
final Object nextReceiver = r.receivers.get(recIdx);
if (nextReceiver instanceof BroadcastFilter) {
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering ordered ["
+ mQueueName + "] to registered "
+ filter + ": " + r);
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
if (r.receiver == null || !r.ordered) {
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
} else {
if (filter.receiverList != null) {
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
// r is guaranteed ordered at this point, so we know finishReceiverLocked()
// will get a callback and handle the activity start token lifecycle.
}
}
return;
}
}
使用ContentProvider,需要先调用ContextWrapper类的getContentResolver方法,mBase不用说,它是ConexImpl对象,
@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
getContentResolver方法返回了ApplicationContentResolver类型的mContentResolver,ApplicationContentResolver是ContextImpl类的静态内部类,继承自ContentResolver,说明当我们调用ContentResolver类的insert、query等方法时,就会启动ContentProvider,我们以query方法为例,query方法实现在ContentResolver类中。
源码路径:frameworks\base\core\java\android\app\ContextImpl.java
private final ApplicationContentResolver mContentResolver;
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
private static final class ApplicationContentResolver extends ContentResolver {
private final ActivityThread mMainThread;
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
return mMainThread.acquireProvider(c,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), false);
}
}
可以看到在ContentResolver类中query有三个重载方法,首先调用acquireUnstableProvider方法返回IContentProvider类型的unstableProvider对象,然后调用unstableProvider的query方法,IContentProvider是ContentProvider的本地代理,具体实现在ContentProvider中。acquireUnstableProvider方法判断uri的scheme是否等于content,接着调用acquireUnstableProvider方法,两个参数的acquireUnstableProvider方法在ApplicationContentResolver类中有重写,调用ActivityThread类的acquireProvider方法。
源码路径:
frameworks\base\core\java\android\content\ContentResolver.java
@Override
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable CancellationSignal cancellationSignal) {
IContentProvider unstableProvider = acquireUnstableProvider(uri);
...
try {
qCursor = unstableProvider.query(mContext.getAttributionSource(), uri, projection,
queryArgs, remoteCancellationSignal);
}
public static final String SCHEME_CONTENT = "content";
public final IContentProvider acquireUnstableProvider(Uri uri) {
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
return null;
}
String auth = uri.getAuthority();
if (auth != null) {
return acquireUnstableProvider(mContext, uri.getAuthority());
}
return null;
}
acquireProvider方法中首先会调用acquireExistingProvider方法检查mProviderMap中是否有目标ContentProvider存在,如果存在直接返回,不存在则调用AMS的getContentProvider方法,installProvider方法用来安装ContentProvider,并将ContentProvider相关数据存储在mProviderMap中,这样就不用每次调用AMS的getContentProvider方法。
源码路径:frameworks\base\core\java\android\app\ActivityThread.java
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;
}
ContentProviderHolder holder = null;
final ProviderKey key = getGetProviderKey(auth, userId);
try {
synchronized (key) {
holder = ActivityManager.getService().getContentProvider(
getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
if (holder != null && holder.provider == null && !holder.mLocal) {
synchronized (key.mLock) {
if (key.mHolder != null) {
if (DEBUG_PROVIDER) {
Slog.i(TAG, "already received provider: " + auth);
}
} else {
key.mLock.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
}
holder = key.mHolder;
}
if (holder != null && holder.provider == null) {
// probably timed out
holder = null;
}
}
}
...
if (holder == null) {
if (UserManager.get(c).isUserUnlocked(userId)) {
Slog.e(TAG, "Failed to find provider info for " + auth);
} else {
Slog.w(TAG, "Failed to find provider info for " + auth + " (user not unlocked)");
}
return null;
}
//安装ContentProvider
holder = installProvider(c, holder, holder.info,
true /*noisy*/, holder.noReleaseNeeded, stable);
return holder.provider;
}
final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
= new ArrayMap<ProviderKey, ProviderClientRecord>();
public final IContentProvider acquireExistingProvider(
Context c, String auth, int userId, boolean stable) {
synchronized (mProviderMap) {
final ProviderKey key = new ProviderKey(auth, userId);
final ProviderClientRecord pr = mProviderMap.get(key);
if (pr == null) {
return null;
}
IContentProvider provider = pr.mProvider;
IBinder jBinder = provider.asBinder();
if (!jBinder.isBinderAlive()) {
handleUnstableProviderDiedLocked(jBinder, true);
return null;
}
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
incProviderRefLocked(prc, stable);
}
return provider;
}
}
getContentProvider方法又调用ContentProviderHelper类的getContentProvider方法,ContentProviderHelper是AMS用来处理内容提供者的类。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
final ContentProviderHelper mCpHelper;
@Override
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String callingPackage, String name, int userId,
boolean stable) {
traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "getContentProvider: ", name);
try {
return mCpHelper.getContentProvider(caller, callingPackage, name, userId, stable);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
getContentProvider方法又调用getContentProviderImpl方法,其中代码很多,核心部分如下,首先调用AMS的getProcessRecordLocked方法获取ProcessRecord对象,它包含ContentProvider的应用程序进程信息,如果该应用进程已经启动则会调用IApplicationThread的scheduleInstallProvider方法,IApplicationThread实现在ActivityThread内部类ApplicationThread中,否则会调用AMS的startProcessLocked方法来启动进程,启动应用程序进程之前已经分析,流程一致,这里我们先分析没有应用程序进程的流程,我们知道应用程序进程启动完后会调用ActivityThread类main方法,然后调用attach方法,最后来到AMS的attachApplicationLocked方法,调用IApplicationThread的bindApplication方法。
源码路径:
frameworks\base\services\core\java\com\android\server\am\ContentProviderHelper.java
ContentProviderHolder getContentProvider(IApplicationThread caller, String callingPackage,
String name, int userId, boolean stable) {
...
return getContentProviderImpl(caller, name, null, callingUid, callingPackage,
null, stable, userId);
}
private final ActivityManagerService mService;
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, int callingUid, String callingPackage, String callingTag,
boolean stable, int userId) {
...
ProcessRecord proc = mService.getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid);
IApplicationThread thread;
if (proc != null && (thread = proc.getThread()) != null
&& !proc.isKilled()) {
if (ActivityManagerDebugConfig.DEBUG_PROVIDER) {
Slog.d(TAG, "Installing in existing process " + proc);
}
final ProcessProviderRecord pr = proc.mProviders;
if (!pr.hasProvider(cpi.name)) {
checkTime(startTime, "getContentProviderImpl: scheduling install");
pr.installProvider(cpi.name, cpr);
try {
thread.scheduleInstallProvider(cpi);
} catch (RemoteException e) {
}
}
} else {
checkTime(startTime, "getContentProviderImpl: before start process");
//启动进程
proc = mService.startProcessLocked(
cpi.processName, cpr.appInfo, false, 0,
new HostingRecord(HostingRecord.HOSTING_TYPE_CONTENT_PROVIDER,
new ComponentName(
cpi.applicationInfo.packageName, cpi.name)),
Process.ZYGOTE_POLICY_FLAG_EMPTY, false, false);
checkTime(startTime, "getContentProviderImpl: after start process");
cpr.launchingApp = proc;
mLaunchingProviders.add(cpr);
}
创建AppBindData对象,传入相关数据,然后发送BIND_APPLICATION消息,传入AppBindData,处理消息调用handleBindApplication方法,首先创建ContextImpl对象,Instrumentation对象并初始化,接着调用installContentProviders方法来启动ContentProvider,最后callApplicationOnCreate方法意味着ContentProvider所在应用程序已经启动。installContentProviders方法中遍历当前应用程序进程的ProviderInfo列表,调用installProvider方法启动这些ContentProvider,最后调用AMS的publishContentProviders方法将这些ContentProvider存储在AMS的mProviderMap中,看下installProvider方法如何启动ContentProvider,首先创建ContentProvider类型的localProvider对象,然后调用它的attachInfo方法,
源码路径:frameworks\base\core\java\android\app\ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
ProviderInfoList providerList, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
SharedMemory serializedSystemFontMap,
long startRequestedElapsedTime, long startRequestedUptime) {
...
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.sdkSandboxClientAppVolumeUuid = sdkSandboxClientAppVolumeUuid;
data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
data.providers = providerList.getList();
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
data.mSerializedSystemFontMap = serializedSystemFontMap;
data.startRequestedElapsedTime = startRequestedElapsedTime;
data.startRequestedUptime = startRequestedUptime;
sendMessage(H.BIND_APPLICATION, data);
}
}
class H extends Handler {
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
Instrumentation mInstrumentation;
private void handleBindApplication(AppBindData data) {
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
final InstrumentationInfo ii;
if (data.instrumentationName != null) {
ii = prepareInstrumentation(data);
} else {
ii = null;
}
if (ii != null) {
initInstrumentation(ii, data, appContext);
} else {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
}
Application app;
app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
}
}
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
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);
}
}
}
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
for (ProviderInfo cpi : providers) {
if (DEBUG_PROVIDER) {
StringBuilder buf = new StringBuilder(128);
buf.append("Pub ");
buf.append(cpi.authority);
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
}
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
ActivityManager.getService().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
...
try {
final java.lang.ClassLoader cl = c.getClassLoader();
LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
if (packageInfo == null) {
// System startup case.
packageInfo = getSystemContext().mPackageInfo;
}
localProvider = packageInfo.getAppFactory()
.instantiateProvider(cl, info.name);
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);
}
attachInfo方法重载最终调用onCreate方法,ContentProvider启动完毕。
源码路径:
frameworks\base\core\java\android\content\ContentProvider.java
public void attachInfoForTesting(Context context, ProviderInfo info) {
attachInfo(context, info, true);
}
public void attachInfo(Context context, ProviderInfo info) {
attachInfo(context, info, false);
}
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
...
ContentProvider.this.onCreate();
}
前面进程存在的情况会调用scheduleInstallProvider方法,和上述流程一致。
本文主要分析了四大组件的工作过程,主要分析它的工作过程,没有详细分析周边代码,只对核心部分进行分析。
四大组件的工作流程大部分是相通的,熟悉了其中一个组件再去看其它组件会简单很多。