第九章 Service的工作过程(下)
(三)Service的工作过程
本节将介绍Service的启动过程和绑定过程,一种是启动状态,主要用于执行后台计算;一种是绑定状态,主要用于其他组件与Service的交互。使用Context的startService和bindService可以完成Service的启动和绑定。
//启动Service
Intent intent = new Intent(this, MyService.class);
startService(intent);
//绑定Service
Intent intent = new Intent(this, TestService.class);
bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
3.1.Service的启动过程
步骤一:从ContextWrapper的startService开始,mBase的类型是ContextImpl,Activity在启动时会通过attach方法讲一个ContextImpl对象关联起来。其大部分操作是通过mBase做的。
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
步骤二:startService方法会调用startServiceCommon方法,而startServiceCommon方法又是通过ActivityManagerNative.getDefault().startService(ActivityManagerNative.getDefault().其实是AMS)的对象来启动一个服务的。
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess();
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
if (cn != null) {
. ...
}
return cn;
} catch (RemoteException e) {
return null;
}
}
步骤三:通过AMS来启动服务的行为是一个远程过程调用,在AMS中,mServices对象类型是ActiveServices,其是一个辅助AMS进行Service的管理(启动、绑定、停止等),在ActiveServices的startServiceLocked中,它在结尾会调用startServiceInnerLocked,调用了bringUpServiceLocked方法,后续的工作在bringUpServiceLocked的realStartServiceLocked方法中处理。
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, int userId) {
....
synchronized(this) {
....
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
ServiceRecord r, boolean callerFg, boolean addToStarting) {
//ServiceRecord 是一个Service记录,一直贯穿Service的启动过程
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();
}
//后续的工作在bringUpServiceLocked的realStartServiceLocked方法中处理
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);
if (error != null) {
return new ComponentName("!!", error);
}
....
return r.name;
}
步骤四:在realStartServiceLocked方法中,app.thread.scheduleCreateService创建Service对象并调用其onCreate,app.thread其实是一个Binder,发送消息给Handler H来处理,通过ActivityThread的handleCreateService方法来完成Service的最终启动。sendServiceArgsLocked调用Service的其他方法,譬如StartCommand。
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
//1.创建Service对象并调用其onCreate,app.thread其实是一个Binder,发送消息给Handler H来处理,通过ActivityThread的handleCreateService方法来完成Service的最终启动。
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
.....
//2.通过该方法调用Service的其他方法,譬如StartCommand
sendServiceArgsLocked(r,execInFg,true)
}
步骤五:handleCreateService方法主要完成了:(1)通过类加载器创建了Service对象;(2)创建Application对象并调用onCreate,只会创建一次;(3)创建ContextImpl并且通过Service的attach方法建立两者的关系;(4)调用Service的onCreate并且将Service独享存储到ActivityThread中的一个列表中;(5)通过handleServiceArgs方法去调用onstartCommond方法。
3.2.Service的绑定过程
步骤一:类似于Service的启动过程,也是从ContextWrapper开始,并通过bindService方法最终调用binServiceCommon方法。
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
步骤二:binServiceCommon方法,完成两件事情:1.将ServiceCommon对象转换为ServiceDispatcher.InnerConnection对象(绑定服务可能是跨进程的,譬如IntentService),ServiceCommon内部类InnerConnection刚好充当了Binder这个角色。2.最后调用了onServiceConnected方法。
感觉看不到意义何在。
(四)BroadcastReceiver的工作过程
BroadcastReceiver先谈谈广播的注册过程,再一个是广播的发送和接收过程。
广播接受者的实现:
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG,"action:" + action);
}
}
静态注册:
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.hzk.receiver" />
</intent-filter>
</receiver>
动态注册:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_ANSWER);
registerReceiver(myReceiver ,intentFilter);
send方法发送广播:
Intent intent = new Intent("com.hzk.receiver");
sendBroadcast(intent);
4.1.广播的注册过程
广播分为静态注册和动态注册两种,静态注册的广播在App安装时有系统完成注册,举例来说是由PackageManagerService来完成整个注册过程。这里分析其动态注册过程。
步骤一:registerReceiver调用了自己的registerReceiverInternal方法,首先从mPackageInfo获取IIntentReceiver对象;其次在AMS中完成广播的真正注册。
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();
}
//1.从mPackageInfo获取IIntentReceiver对象
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
//2.AMS中完成代码的真正注册。
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}
步骤二:在AMS中,会把远程的InnerReceiver和IntentFilter对象存储起来,这样整个广播的注册过程就完成了。
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
....
mRegisteredReceivers.put(receiver.asBinder(),r1);
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadast");
}
mReceiverResolver.addFilter(bf);
...
return sticky;
}
}
4.2.广播的发送和接收过程
当Send方法发送广播时,AMS会找出匹配的广播接收者并将广播发送给它们处理,广播发送的类型有:普通广播、有序广播和粘性广播。后两者与普通广播具有不同特性,但发送/接收流程类似,故而我们只分析普通广播的实现。
步骤一:发送广播始于ContextWrapper的senBroadCast方法,其并不做什么,将事情交给ContextImpl去处理。其直接向AMS发送一个异步请求用于发送广播。
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
//直接向AMS发送一个异步请求用于发送广播
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false,
getUserId());
} catch (RemoteException e) {
}
}
步骤二:在AMS中的broadcastIntent调用了broadcastIntentLocked方法,该方法用来筛选广播。
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, int appOp, boolean serialized, boolean sticky, int userId) {
....
//调用了broadcastIntentLocked方法,用来配置BroadCastReceiver的相关配置,怎么发送?怎么进行匹配?
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, appOp, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
步骤三:在broadcastIntentLocked方法中,Android5.0下默认情况下广播不会发送给已经停止的应用,可以使用FLAGS进行控制是否发送给已经停止的应用。使用Intent-filter查找出匹配的广播接收者并经过一些列的条件过滤,最终将满足条件的广播接收者添加到BroadcastQueue中,此时BroadcastQueue会将其发送给相应的广播接受者。如果是无序广播,则会遍历广播存储,最后onReceiver会被执行。
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
// If we are not serializing this broadcast, then send the
// registered receivers separately so they don't wait for the
// components to be launched.
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermission,
appOp, registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(
TAG, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
final BroadcastReceiver receiver = mReceiver;
receiver.setPendingResult(this);
receiver.onReceiver(mContext,intent);
(五)ContentProvider的工作过程
ContentProvider是一个内存共享型组件,通过Binder向其他组件乃至其他应用提供数据,当ContentProvider所在的进程启动的时候,ContentProvider会同时启动并且发布到AMS中,需要注意的是,这个时候ContentProvider的onCreate要先于Application的onCreate执行。
启动过程:
(1)一个应用启动的时候,入口方法在ActivityThread中的main里,main是一个静态方法,在main中会创建ActivityThread的实例并创建主线程的消息队列;
(2)在ActivityThread的attach中远程调用AMS的attachApplication方法并将ActivityThread提供给AMS;
(3)ActivityThread是一个Binder对象,他的Binder接口是IApplicationThread,他主要用于ActivityThread和AMS之间的通信,会调用ApplicationThread的bindApplication方法,注意这个过程同样是跨进程完成的,
(4)bindApplication的逻辑是经过ActivityThread中的mHander切换到ActivityThread执行,具体是方法是handlerBindApplication,在handlerApplication方法中,ActivityThread会加载一个ContentProvider,然后再调用Application的onCreate方法。
需要说明的是,handlerBindApplication的功能是:(1)创建ContextImpl和Instrumentation;(2)创建Application对象;(3)启动当前进程的ContentProvider并调用其onCreate方法;(4)调用Application的onCreate方法。