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