启动Service有两种方式:startService 与bindService。
对Service的管理主要集中在ActiveServices和ServiceMap中。下面主要熟悉启动服务的流程。
一、startService流程
step 1、ContextImpl.startService(Intent service)
step 2、ContextImpl.startServiceCommon()
step 3、AMS.startService();
step 4、ActiveServices.startServiceLocked();
前面三个步骤的调用非常简单,就不分析了,直接分析ActiveServices.startServiceLocked()
ComponentName startServiceLocked(IApplicationThread caller,
Intent service, String resolvedType,
int callingPid, int callingUid, int userId) {
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
final boolean callerFg;
if (caller != null) {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when starting service " + service);
}
callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
} else {
callerFg = true;
}
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
callingPid, callingUid, userId, true, callerFg); //①从ServiceMap中检索对应的ServiceRecord,如果是第一次启动则不存在,这时new ServiceRecord/ServiceRestarterv,并保存在ServiceMap中。
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null);
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.lastActivity = SystemClock.uptimeMillis(); //②初始化ServiceRecord成员变量
r.startRequested = true;
r.delayedStop = false;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants)); //③new ServiceRecord.StartItem并加入ServiceRecord. 加入pendingStarts中,表示启动该Service过程中启动参数还未deliver到ActivityThread中(具体就是调用ActivityThread.scheduleServiceArgs()-->Service.onStartCommand ()), deliver后便从pendingStarts中删除并重新加入deliveredStarts中。
final ServiceMap smap = getServiceMap(r.userId);
boolean addToStarting = false;
if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) {
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
// If this is not coming from a foreground caller, then we may want
// to delay the start if there are already other background services
// that are starting. This is to avoid process start spam when lots
// of applications are all handling things like connectivity broadcasts.
// We only do this for cached processes, because otherwise an application
// can have assumptions about calling startService() for a service to run
// in its own process, and for that process to not be killed before the
// service is started. This is especially the case for receivers, which
// may start a service in onReceive() to do some additional work and have
// initialized some global state as part of that.
if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Potential start delay of " + r + " in "
+ proc);
if (r.delayed) {
// This service is already scheduled for a delayed start; just leave
// it still waiting.
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Continuing to delay: " + r);
return r.name;
}
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
// Something else is starting, delay!
Slog.i(TAG, "Delaying start of: " + r);
smap.mDelayedStartList.add(r);
r.delayed = true;
return r.name;
}
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Not delaying: " + r);
addToStarting = true;
} else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
// We slightly loosen when we will enqueue this new service as a background
// starting service we are waiting for, to also include processes that are
// currently running other services or receivers.
addToStarting = true;
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Not delaying, but counting as bg: " + r);
} else if (DEBUG_DELAYED_STATS) {
StringBuilder sb = new StringBuilder(128);
sb.append("Not potential delay (state=").append(proc.curProcState)
.append(' ').append(proc.adjType);
String reason = proc.makeAdjReason();
if (reason != null) {
sb.append(' ');
sb.append(reason);
}
sb.append("): ");
sb.append(r.toString());
Slog.v(TAG, sb.toString());
}
}
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); //④继续调用startServiceInnerLocked()
}
step 5、ActiveServices.startServiceInnerLocked()
函数直接调用bringUpServiceLocked()
step 6、ActiveServices.bringUpServiceLocked()
private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean execInFg, boolean whileRestarting) {
………….
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
if (app != null && app.thread != null) { //①如果Service所在的进程已运行,那么直接调用realStartServiceLocked()启服务。
try {
app.addPackage(r.appInfo.packageName, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
}
………
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null) { //②如果Service所在的进程没有运行,那么先启动进程,并把ServiceRecord加入mPendingServices中。启动进程时调用AMS.attachApplicationLocked()ActiveServices. attachApplicationLocked(),在这个函数中会针对mPendingServices中的Service分别调用realStartServiceLocked()来启动Service。
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
………
}
step 7、ActiveServices.realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
if (DEBUG_MU)
Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+ ", ProcessRecord.uid = " + app.uid);
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
app.services.add(r); //①将ServiceRecord添加到ProcessRecord.services中
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
boolean created = false;
try {
String nameTerm;
int lastPeriod = r.shortName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState); //②ActivityThread.scheduleCreateService()ActivityThread. handleCreateService(),回调应用层的函数,在进程主线程中创建Service对象、初始化上下文、调用onCreate()等
r.postNotification();
created = true;
} finally {
if (!created) {
app.services.remove(r);
r.app = null;
scheduleServiceRestartLocked(r, false);
}
}
requestServiceBindingsLocked(r, execInFg); //③对于startService()启动的服务,该函数直接返回;对于BinderService()启动的服务,该函数会回调ActivityTread. scheduleBindService()函数,ActivityTread. scheduleBindService()handleBindService()service.onBind();AMS. publishService ()ActiveServices. publishServiceLocked(ServiceRecord r, Intent intent, IBinder service),后面将详细分析publishServiceLocked().
// If the service is in the started state, and there are no
// pending arguments, then fake up one so its onStartCommand() will
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
sendServiceArgsLocked(r, execInFg, true); //④deliver一些参数到ActivityThread中,sendServiceArgsLocked()ActivityThread.scheduleServiceArgs()handleServiceArgs()service. onStartCommand()
if (r.delayed) {
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "REM FR DELAY LIST (new proc): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Applying delayed stop (from start): " + r);
stopServiceLocked(r);
}
}
}
step 8、publishServiceLocked()
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { //①参数service来自service.onBind()的返回值。对于BindService()启动的服务一般通过Service.onBind()来返回该Service所实现的interface。service.onBind()的返回值保存在两个地方,一个是IntentBindRecord.binder,另一个通过ConnectionRecord.conn.connected(r.name, service)发布给ActivityTread,上层应用通过ServiceConnection接收到这个IBinder。
final long origId = Binder.clearCallingIdentity();
try {
if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
+ " " + intent + ": " + 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;
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);
if (!filter.equals(c.binding.intent.intent)) {
if (DEBUG_SERVICE) Slog.v(
TAG, "Not publishing to: " + c);
if (DEBUG_SERVICE) Slog.v(
TAG, "Bound intent: " + c.binding.intent.intent);
if (DEBUG_SERVICE) Slog.v(
TAG, "Published intent: " + intent);
continue;
}
if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
try {
c.conn.connected(r.name, service); //②ConnectionRecord. Conn中保存的是IServiceConnection的代理对象,本地对象保存在LoadedApk. ServiceDispatcher. mIServiceConnection中(InnerConnection对象),函数会调用到InnerConnection. Connected() ServiceDispatcher. Connected()-->RunConnection().run()-->doConnected()-->ServiceConnection.onServiceConnected(),<span style="font-family: Arial, Helvetica, sans-serif;">service最终被发布到</span><pre name="code" class="java" style="font-size: 18px;">ServiceConnection.onServiceConnected()中,应用便可通过该函数获取service.onBind()返回的对象。
} catch (Exception e) { Slog.w(TAG, "Failure sending service " + r.name + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } } } } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); } }
至此,startService()流程便走完了。
二、bindService流程
LoadApk.ServiceDispatcher.InnerConnection继承IServiceConnection.stub,只包含一个Connected()函数。IServiceConnection的存在就是为了给AMS在bindService过程中与应用层通信的接口。IServiceConnection的本地对象保存在ServiceDispatcher.mIServiceConnection中,代理对象保存在ConnectionRecord.conn中。IServiceConnection的代理对象是通过LoadApk.getServiceDispatcher()获取,然后传入AMS中。
step 1、ContextWrapper.bindService()
step 2、ContextImpl.bindService()
step 3、ContextImpl.bindServiceCommon()
step 4、LoadApk.getServiceDispatcher()
step 5、AMS.bindService()
step 6、ActiveServices.bindServiceLocked()
前面5个步骤很简单,重点在这个函数,仔细分析下。
int bindServiceLocked(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); //①根据IApplicationThread找到对应的ProcessRecord。
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when binding service " + service);
}
ActivityRecord activity = null;
if (token != null) { //②一般来说token为null,参数Token的来源:ContextImpl. getActivityToken()retrun mActivityToken, mActivityToken的赋值在ContextImpl. Init()中完成。
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
…………..
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg); //③创建ServiceRecord并保存返回
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
final long origId = Binder.clearCallingIdentity();
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); //④从serviceRecord. Bindings. Apps中检索AppBindRecord。如果不存在那么new AppBindRecord.
ConnectionRecord c = new ConnectionRecord(b, activity, //⑤创建一个ConnectionRecord,然后加加加加入一堆数据结构中
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) { //③起service,在第一部分已分析。
return 0;
}
}
………….
return 1;
}
bringUpServiceLocked()函数中调用realStartServiceLocked()来起服务。后面的过程跟startService()的过程一样,就不重复了。
step 8、ActiveServices.realStartServiceLocked
step 9、app.thread.scheduleCreateService
step 10、ActiveServices.requestServiceBindingsLocked
step 11、ActiveServices.sendServiceArgsLocked
最后再研究下retrieveServiceLocked()函数:
private ServiceLookupResult retrieveServiceLocked(Intent service, //①检索service,如果存在对应的ServiceRecord,那么返回不为null,如果不存在,但是createIfNeeded=true,那么会创建一个ServiceRecord,保存并返回。说白了这个函数就是两个功能:1、检索ServiceRecord(createIfNeeded=false);2、创建ServiceRecord并保存(createIfNeeded=true)
String resolvedType, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg){
ServiceRecord r = null;
if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
+ " type=" + resolvedType + " callingUid=" + callingUid);
userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
false, true, "service", null);
ServiceMap smap = getServiceMap(userId); //②Service在AMS中是被ActiveServices和ServiceMap管理着,一个Service在AMS侧对应着一个ServiceRecord对象,这个ServiceRecord保存在两个地方,分别是ServiceMap. mServicesByName和ServiceMap. mServicesByIntent中
final ComponentName comp = service.getComponent();
if (comp != null) {
r = smap.mServicesByName.get(comp);
}
if (r == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
r = smap.mServicesByIntent.get(filter);
}
if (r == null) {
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveService(
service, resolvedType,
ActivityManagerService.STOCK_PM_FLAGS, userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
Slog.w(TAG, "Unable to start service " + service + " U=" + userId +
": not found");
return null;
}
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
if (userId > 0) {
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
sInfo.name, sInfo.flags)) {
userId = 0;
smap = getServiceMap(0);
}
sInfo = new ServiceInfo(sInfo);
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
}
r = smap.mServicesByName.get(name);
if (r == null && createIfNeeded) {
Intent.FilterComparison filter
= new Intent.FilterComparison(service.cloneFilter());
ServiceRestarter res = new ServiceRestarter();
BatteryStatsImpl.Uid.Pkg.Serv ss = null;
BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
ss = stats.getServiceStatsLocked(
sInfo.applicationInfo.uid, sInfo.packageName,
sInfo.name);
}
r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
res.setService(r);
smap.mServicesByName.put(name, r);
smap.mServicesByIntent.put(filter, r);
// Make sure this component isn't in the pending list.
for (int i=mPendingServices.size()-1; i>=0; i--) {
ServiceRecord pr = mPendingServices.get(i);
if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
&& pr.name.equals(name)) {
mPendingServices.remove(i);
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
if (r != null) {
if (mAm.checkComponentPermission(r.permission,
callingPid, callingUid, r.appInfo.uid, r.exported)
!= PackageManager.PERMISSION_GRANTED) {
if (!r.exported) {
Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " that is not exported from uid " + r.appInfo.uid);
return new ServiceLookupResult(null, "not exported from uid "
+ r.appInfo.uid);
}
Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " requires " + r.permission);
return new ServiceLookupResult(null, r.permission);
}
if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
resolvedType, r.appInfo)) {
return null;
}
return new ServiceLookupResult(r, null);
}
return null;
}