这篇文章主要讲的是分真正两种情况启动service,一种是service运行的进程和app进程是同一个进程,还有一种是运行在独立进程中。AMS端的调度流程可以参考之前的文章juejin.cn/post/710046…
ActiveServices#bringUpServiceLocked 这个方法会判断service要运行的进程情况,
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
.......
// step3.1 查找对应的进程
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
// 进程存在
if (app != null && app.thread != null) {
try {
// step3.2 启动service
realStartServiceLocked(r, app, execInFg);
return null;
}
}
// 进程未启动
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
// step3.3 启动进程
if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
bringDownServiceLocked(r);
return msg;
}
}
return null;
}
这是上一篇分析到的地方,下面继续分析后面的流程。
在app进程中运行service - realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
....
// 添加到app进程的service集合
final boolean newService = app.services.add(r);
....
try {
// step1 调用app进程 创建service
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
}
// step2 请求bind
requestServiceBindingsLocked(r, execInFg);
....
// step3 调用onStartCommand
sendServiceArgsLocked(r, execInFg, true);
....
}
step1调用app进程 创建service
调用到ActivityThread内部ApplicationThread bind对象,
// 参数一 对应的是ServiceRecord,后面再传给ams
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;
// 只是往主线程插入一个消息,AMS就返回了
sendMessage(H.CREATE_SERVICE, s);
}
调用到handler H对象。
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
// 创建service对象
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
....
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 调用生命周期oncreate
service.onCreate();
mServices.put(data.token, service);
// 通知ams service创建好了
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
service的生命周期oncreate就执行了。
step2 请求bind requestServiceBindingsLocked
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
// 遍历所有的绑定了 该service的client
for (int i = r.bindings.size() - 1; i >= 0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
// 调用用户进程scheduleBindService
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
}
}
return true;
}
执行到ActivityThread的applicationthread
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;
// 只是往主线程插入一个消息,AMS就返回了
sendMessage(H.BIND_SERVICE, s);
}
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
try {
if (!data.rebind) {
// 调用service的生命周期onBind
IBinder binder = s.onBind(data.intent);
// step3 将binder发布到ams
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
// 生命周期onRebind,跟我们本次讨论的关系不大
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
}
}
}
}
调用了service的onBind 获取到binder对象,并发布到ams。
step3 将binder发布到ams
public void publishService(IBinder token, Intent intent, IBinder service) {
synchronized (this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
//ActiveServices#publishServiceLocked,直接强转得到ServiceRecord
mServices.publishServiceLocked((ServiceRecord) token, intent, service);
}
}
ActiveServices#publishServiceLocked
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
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;
for (int conni = r.connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord c = clist.get(i);
try {
// 调用IServiceConnection的connected
c.conn.connected(r.name, service, false);
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
}
}
ams根据token找到对应的ServiceRecord,遍历调用IServiceConnection的connected。IServiceConnection是之前app端实现的ServiceDispatcher,可参考juejin.cn/post/710007…
ServiceDispatcher的定义,内部持有ServiceDispatcher.InnerConnection的binder对象,用于进程间通信,回调的就是 InnerConnection#connected方法
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final Handler mActivityThread;
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
//mIServiceConnection 是InnerConnection类型
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
}
// 实现了IServiceConnection.Stub的binder对象,
private static class InnerConnection extends IServiceConnection.Stub {
// 持有ServiceDispatcher的弱引用
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
public void connected(ComponentName name, IBinder service, boolean dead) {
// mActivityThread是 ActivityThread中的handler H
if (mActivityThread != null) {
// 分支step 3.1
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
connected内部又调用了ServiceDispatcher的connected方法。方法内判断mActivityThread是否为空,从之前的 juejin.cn/post/710007… bindService流程一文章可见,mActivityThread不为空,就等于ActivityThread中的handler H对象。所以进入上面的分支step 3.1 给handler发送了一个runnable -- RunConnection。代码如下:
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;
}
看看构造函数和run方法。入参mCommand = 0,mDead = false 所以执行doConnected方法。
static final class ServiceDispatcher {
private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
= new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
old = mActiveConnections.get(name);
if (service != null) {
// 创建ConnectionInfo,保存到mActiveConnections
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
try {
mActiveConnections.put(name, info);
}
}
}
// If there is a new viable service, it is now connected.
if (service != null) {
// 回调bindservice时提供的ServiceConnected接口
mConnection.onServiceConnected(name, service);
}
}
}
到这里回调到回调bindservice时提供的ServiceConnected接口的onServiceConnected,这个方法里我们可以获取到service的代理对象。
启动新的进程运行service - mAm.startProcessLocked
我们在下一篇中继续分析启动新进程运行service。
参考资料: www.jianshu.com/p/18e4efa2e… www.jianshu.com/p/f2db0f58d…