Android服务启动之StartService源码分析

来源:互联网 发布:mac智能文件夹怎么用 编辑:程序博客网 时间:2024/05/17 23:46

在编写Android应用程序时,我们一般将比较耗时的操作放在一个独立的进程来处理,这样主进程仍然可以流畅地响应界面事件,提高用户体验。Android系统为我们提供了一个Service类,我们可以实现一个以Service为基类的服务子类,在里面实现自己的计算型逻辑,然后在主进程通过startService函数来启动这个服务。在本文中,将详细分析应用程序进程是如何通过startService函数来启动自定义服务的。


请求启动Service


frameworks\base\core\java\android\content\Context.java

public abstract ComponentName startService(Intent service);
在Context类中定义了抽象方法startService,该函数由Context的子类ContextImpl实现。

frameworks\base\core\java\android\content\ContextWrapper.java

public ComponentName startService(Intent service) {return mBase.startService(service);}
mBase为ContextImpl类型对象

frameworks\base\core\java\android\app\ContextImpl.java

public ComponentName startService(Intent service) {try {service.setAllowFds(false);//调用ActivityManagerService服务的Binder远程代理发送启动Service的参数ComponentName cn = ActivityManagerNative.getDefault().startService(mMainThread.getApplicationThread(), service,service.resolveTypeIfNeeded(getContentResolver()));if (cn != null && cn.getPackageName().equals("!")) {throw new SecurityException("Not allowed to start service " + service+ " without permission " + cn.getClassName());}return cn;} catch (RemoteException e) {return null;}}
ActivityManagerNative.getDefault()将得到ActivityManagerProxy对象,参数mMainThread.getApplicationThread()表示为当前启动服务进程的ApplicationThread对象,参数service.resolveTypeIfNeeded(getContentResolver())返回当前传输的Intent的MEMI号,关于Binder进程间RPC调用过程这里不在详细分析,有兴趣可以参考Android服务函数远程调用源码分析。通过ActivityManagerNative.getDefault().startService()调用,将Service的启动交给SystemServer进程的ActivityManagerService服务来完成。

frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

public ComponentName startService(IApplicationThread caller, Intent service,String resolvedType) {// Refuse possible leaked file descriptorsif (service != null && service.hasFileDescriptors() == true) {throw new IllegalArgumentException("File descriptors passed in Intent");}synchronized(this) {//读取启动服务的应用程序进程的PID和UIDfinal int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();ComponentName res = startServiceLocked(caller, service,resolvedType, callingPid, callingUid);Binder.restoreCallingIdentity(origId);return res;}}

参数caller是启动服务的应用程序进程的ApplicationThread实例,比如说Launcher启动服务,那么这个caller就是Launcher进程的ApplicationThread实例,每一个Android应用程序进程都有且只有一个ActivityThread实例,每一个ActivityThread实例中又定义了一个ApplicationThread对象。接下来调用startServiceLocked函数来启动服务

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

ComponentName startServiceLocked(IApplicationThread caller,Intent service, String resolvedType,int callingPid, int callingUid) {synchronized(this) {if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service+ " type=" + resolvedType + " args=" + service.getExtras());if (caller != null) {//通过ApplicationThread对象从ActivityManagerService的成员变量mLruProcesses列表中查找启动服务的进程在ActivityManagerService中的ProcessRecord对象,变量mLruProcesses的说明: /** * List of running applications, sorted by recent usage. * The first entry in the list is the least recently used. * It contains ApplicationRecord objects.  This list does NOT include * any persistent application records (since we never want to exit them). */final ProcessRecord callerApp = getRecordForAppLocked(caller);if (callerApp == null) {throw new SecurityException("Unable to find app for caller " + caller+ " (pid=" + Binder.getCallingPid()+ ") when starting service " + service);}}        //解析service这个Intent         /**         * private final class ServiceLookupResult { *final ServiceRecord record; ServiceRecord用于在服务端描述一个Service信息 *final String permission; *ServiceLookupResult(ServiceRecord _record, String _permission) { *record = _record; *permission = _permission; *} * };         */ServiceLookupResult res = retrieveServiceLocked(service, resolvedType,callingPid, callingUid, UserId.getUserId(callingUid));//系统中没有注册此Serviceif (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 = checkGrantUriPermissionFromIntentLocked(callingUid, r.packageName, service, service.getFlags(), null);if (unscheduleServiceRestartLocked(r)) {if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);}//初始化服务端的ServiceRecord信息r.startRequested = true;r.callStart = false;r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),service, neededGrants));r.lastActivity = SystemClock.uptimeMillis();synchronized (r.stats.getBatteryStats()) {r.stats.startRunningLocked();}//进一步启动Serviceif (!bringUpServiceLocked(r, service.getFlags(), false)) {return new ComponentName("!", "Service process is bad");}return r.name;}}
ActivityManagerService在请求Zygote进程孵化新的应用程序进程时,在ActivityManagerService服务端为每一个应用程序进程创建了对应的ProcessRecord对象来描述新的应用程序进程信息,关于ActivityManagerService请求孵化新应用程序过程请参考Android 应用进程启动过程的源码分析。函数首先根据应用程序进程中的IApplicationThread对象在最近启动的应用程序列表mLruProcesses中为服务启动进程查找对应的ProcessRecord对象,如果启动Service的应用程序进程还未启动,则抛出SecurityException异常。然后调用retrieveServiceLocked函数为当前启动的Service在ActivityManagerService服务端创建一个ServiceRecord对象来描述当前Service的信息。

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private ServiceLookupResult retrieveServiceLocked(Intent service,String resolvedType, int callingPid, int callingUid, int userId) {ServiceRecord r = null;if (DEBUG_SERVICE)Slog.v(TAG, "retrieveServiceLocked: " + service + " type=" + resolvedType+ " callingUid=" + callingUid);//根据Service的包名从ActivityManagerService的成员变量mServiceMap中查找对应的ServiceRecord对象if (service.getComponent() != null) {r = mServiceMap.getServiceByName(service.getComponent(), userId);}//根据启动Service的Intent信息从成员变量mServiceMap中查找对应的ServiceRecord对象if (r == null) {Intent.FilterComparison filter = new Intent.FilterComparison(service);r = mServiceMap.getServiceByIntent(filter, userId);}//如果mServiceMap中不存在当前启动的Service对应的ServiceRecord对象if (r == null) {try {//从PackageManager服务中获取当前启动Service的相关信息,并构造ResolveInfo对象ResolveInfo rInfo =AppGlobals.getPackageManager().resolveService(service, resolvedType, STOCK_PM_FLAGS, userId);//获取Service信息对象ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;if (sInfo == null) {Slog.w(TAG, "Unable to start service " + service +  ": not found");return null;}if (userId > 0) {if (isSingleton(sInfo.processName, sInfo.applicationInfo)) {userId = 0;}sInfo.applicationInfo = getAppInfoForUser(sInfo.applicationInfo, userId);}ComponentName name = new ComponentName(sInfo.applicationInfo.packageName, sInfo.name);//再次根据Service的包名从成员变量mServiceMap中查找对应的ServiceRecord对象r = mServiceMap.getServiceByName(name, userId);//依然查找不到if (r == null) {Intent.FilterComparison filter = new Intent.FilterComparison(service.cloneFilter());//为当前Service构造一个重启服务的Runnable对象ServiceRestarter res = new ServiceRestarter();BatteryStatsImpl.Uid.Pkg.Serv ss = null;BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();synchronized (stats) {ss = stats.getServiceStatsLocked(sInfo.applicationInfo.uid, sInfo.packageName,sInfo.name);}//为当前Service构造ServiceRecord对象r = new ServiceRecord(this, ss, name, filter, sInfo, res);//设置ServiceRestarter重启的服务为当前Serviceres.setService(r);//将当前Service的服务端描述符ServiceRecord保存到mServiceMap中mServiceMap.putServiceByName(name, UserId.getUserId(r.appInfo.uid), r);mServiceMap.putServiceByIntent(filter, UserId.getUserId(r.appInfo.uid), r);//通过服务名称查找mPendingServices服务列表中是否存在当前Serviceint N = mPendingServices.size();for (int i=0; i<N; i++) {ServiceRecord pr = mPendingServices.get(i);if (pr.name.equals(name)) {mPendingServices.remove(i);i--;N--;}}}} catch (RemoteException ex) {// pm is in same process, this will never happen.}}if (r != null) {//检查服务权限if (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);}//返回ServiceLookupResult对象return new ServiceLookupResult(r, null);}return null;}
该函数通过一系列处理后,为当前启动的Service构造了对应的ServiceRecord对象,并保存到ActivityManagerService的成员变量mServiceMap中,这样就相当于在ActivityManagerService服务端完成了服务登记工作,接下来将调用bringUpServiceLocked函数正式启动这个已经记录在案的Service。

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private final boolean bringUpServiceLocked(ServiceRecord r,int intentFlags, boolean whileRestarting) {//如果该Service服务已经创建,再次调用startService时,只调用该Service的onStartCommand来运行该Serviceif (r.app != null && r.app.thread != null) {//启动ServicesendServiceArgsLocked(r, false);return true;}if (!whileRestarting && r.restartDelay > 0) {// If waiting for a restart, then do nothing.return true;}if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);// 将当前启动的Service从服务重启列表mRestartingServices中移除mRestartingServices.remove(r);// Service is now being launched, its package can't be stopped.try {AppGlobals.getPackageManager().setPackageStoppedState(r.packageName, false, r.userId);} catch (RemoteException e) {} catch (IllegalArgumentException e) {Slog.w(TAG, "Failed trying to unstop package "+ r.packageName + ": " + e);}//判断此Service是否在独立的进程中启动final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;//得到在XML中设置该Service运行的进程名称final String appName = r.processName;ProcessRecord app;//当前Service运行在应用程序进程,并非独立进程if (!isolated) {//根据进程名称及UID从ActivityManagerService的成员变量mProcessNames中查找进程对应的描述符ProcessRecordapp = getProcessRecordLocked(appName, r.appInfo.uid);if (DEBUG_MU)Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);if (app != null && app.thread != null) {try {app.addPackage(r.appInfo.packageName);//在现有的进程中启动ServicerealStartServiceLocked(r, app);return true;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting service " + r.shortName, e);}}} else {// If this service runs in an isolated process, then each time// we call startProcessLocked() we will get a new isolated// process, starting another process if we are currently waiting// for a previous process to come up.  To deal with this, we store// in the service any current isolated process it is running in or// waiting to have come up.app = r.isolatedProc;}// Not running -- get it started, and enqueue this service record// to be executed when the app comes up.if (app == null) {//启动应用程序进程if ((app=startProcessLocked(appName, r.appInfo, true, intentFlags,"service", r.name, false, isolated)) == null) {Slog.w(TAG, "Unable to launch app "+ r.appInfo.packageName + "/"+ r.appInfo.uid + " for service "+ r.intent.getIntent() + ": process is bad");//强制退出ServicebringDownServiceLocked(r, true);return false;}if (isolated) {r.isolatedProc = app;}}//当ActivityManagerService服务还为准备好时,mPendingServices用于保存客户进程请求启动的Servcie//保存当前请求启动的Serviceif (!mPendingServices.contains(r)) {mPendingServices.add(r);}return true;}
如果当前系统中已经存在运行该Service的进程,则调用函数realStartServiceLocked来进一步启动Service,realStartServiceLocked函数的第一个参数是当前启动的Service在ActivityManagerService服务中的描述符对象ServiceRecord,第二个参数则是运行该Service的进程在ActivityManagerService服务中的描述符对象ProcessRecord,有了启动的Service和运行该Service的进程,接下来就可以真正启动该Service了。

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app) 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);// LC_RAM_SUPPORTif (LC_RAM_SUPPORT) {r.appAdj = ProcessRecord.TMP_CUR_ADJ_DEFAULT;r.hasFixAdj = (app.fixAdj != ProcessRecord.TMP_FIX_ADJ_DEFAULT);}r.app = app;r.restartTime = r.lastActivity = SystemClock.uptimeMillis();//在ActivityManagerService服务中记录当前进程中运行的所有Serviceapp.services.add(r);bumpServiceExecutingLocked(r, "create");//mLruProcesses保存系统最近运行的应用程序进程信息,更新当前ProcessRecord在mLruProcesses变量中的状态updateLruProcessLocked(app, true, true);boolean created = false;try {mStringBuilder.setLength(0);r.intent.getIntent().toShortString(mStringBuilder, true, false, true, false);EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,System.identityHashCode(r), r.shortName,mStringBuilder.toString(), r.app.pid);synchronized (r.stats.getBatteryStats()) {r.stats.startLaunchedLocked();}//检查当前Service所在包是否经过Dex优化过ensurePackageDexOpt(r.serviceInfo.packageName);//创建Service服务app.thread.scheduleCreateService(r, r.serviceInfo,compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));r.postNotification();created = true;} finally {if (!created) {app.services.remove(r);scheduleServiceRestartLocked(r, false);}}//绑定该Service服务requestServiceBindingsLocked(r);// 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));}//启动该Service服务sendServiceArgsLocked(r, true);}
在该函数中完成了Service的创建,Service的绑定,Service的启动。无论是Service的创建,绑定还是启动过程,都是由ActivityManagerService服务调度应用程序进程来完成的,通过Binder跨进程调用来实现。在此之前Service启动的前期工作都是在ActivityManagerService中完成,主要是实现Service的备案:



Service创建过程


ActivityManagerService通过Binder跨进程调用应用程序进程中的ApplicationThread的scheduleCreateService函数在应用程序进程中加载Service类,并创建Service对象。
frameworks\base\core\java\android\app\ActivityThread.$ApplicationThread
public final void scheduleCreateService(IBinder token,ServiceInfo info, CompatibilityInfo compatInfo) {CreateServiceData s = new CreateServiceData();s.token = token;//ServiceRecord Binder本地对象s.info = info;s.compatInfo = compatInfo;queueOrSendMessage(H.CREATE_SERVICE, s);}
在ActivityThread类中定义了一个内部类H,继承于Handler,在Android应用程序进程启动过程中,我们介绍了Zygote进程通过复制一份自身进程地址空间来实现子进程的创建过程,孵化出来新的应用程序进程通过加载ActivityThread类,并调用该类的main函数为应用程序主线程建立消息循环,而定义的H这个Handler正是向主线程消息循环发送消息的通道,在这个函数中,将ActivityManagerService服务通过Binder跨进程调用Service运行进程的scheduleCreateService函数转换为本地的一个异步调用。在该函数中,将函数调用参数信息封装为CreateServiceData对象,然后通过queueOrSendMessage函数向应用程序主线程消息循环中发送一个CREATE_SERVICE消息,在H的handleMessage()函数中,完成对该消息的处理:
frameworks\base\core\java\android\app\ActivityThread.$H
public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case CREATE_SERVICE:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");handleCreateService((CreateServiceData)msg.obj);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}}
这里又将Service的创建工作交给H的外部类ActivityThread的handleCreateService()函数来完成。
frameworks\base\core\java\android\app\ActivityThread.java
private void handleCreateService(CreateServiceData data) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();//加载启动的Service类LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);Service service = null;try {java.lang.ClassLoader cl = packageInfo.getClassLoader();service = (Service) cl.loadClass(data.info.name).newInstance();} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to instantiate service " + data.info.name+ ": " + e.toString(), e);}}try {if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);//为该Service创建一个上下文ContextImpl对象ContextImpl context = new ContextImpl();context.init(packageInfo, null, this);Application app = packageInfo.makeApplication(false, mInstrumentation);context.setOuterContext(service);//将Application,ActivityManagerService,当前Service在SystemServer进程中的ServiceRecord引用保存到当前Service的成员变量中service.attach(context, this, data.info.name, data.token, app,ActivityManagerNative.getDefault());//回调当前启动Service的onCreate函数service.onCreate();//变量mServices保存了应用程序进程中运行的所有ServicemServices.put(data.token, service);//从应用程序进程进入SystemServer进程try {//通知ActivityManagerService服务,当前Service创建完成ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, 0, 0, 0);} catch (RemoteException e) {// nothing to do.}} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to create service " + data.info.name+ ": " + e.toString(), e);}}}
在前面我们已经知道当前启动的Service在ActivityManagerService中已经记录在mServiceMap成员变量中了,对于运行Service的应用程序进程来说,仍然需要记录该进程中运行的Service信息,并保存在ActivityThread的成员变量mServices中。在该函数中加载启动Service的类,并为Service创建一个上下文对象,同时回调Service的onCreate()函数完成Service的创建过程。


Service绑定过程


frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
private final void requestServiceBindingsLocked(ServiceRecord r) {//遍历当前Service的成员变量bindingsIterator<IntentBindRecord> bindings = r.bindings.values().iterator();while (bindings.hasNext()) {IntentBindRecord i = bindings.next();//调用requestServiceBindingLocked()函数绑定前Serviceif (!requestServiceBindingLocked(r, i, false)) {break;}}}
ServiceRecord的成员变量bindings中保存了需要绑定当前Service的IntentBindRecord对象,在该函数中就是遍历bindings列表,然后调用requestServiceBindingLocked()函数来与当前Service绑定
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
private final boolean requestServiceBindingLocked(ServiceRecord r,IntentBindRecord i, boolean rebind) {if (r.app == null || r.app.thread == null) {// If service is not currently running, can't yet bind.return false;}if ((!i.requested || rebind) && i.apps.size() > 0) {try {bumpServiceExecutingLocked(r, "bind");//请求绑定服务r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);if (!rebind) {i.requested = true;}i.hasBound = true;i.doRebind = false;} catch (RemoteException e) {if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);return false;}}return true;}
ActivityManagerService通过跨进程调用Service运行进程ApplicationThread的scheduleBindService函数来绑定服务
frameworks\base\core\java\android\app\ActivityThread.$ApplicationThread
public final void scheduleBindService(IBinder token, Intent intent,boolean rebind) {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());queueOrSendMessage(H.BIND_SERVICE, s);}
将ActivityManagerService的RPC调用转换为本地异步调用
frameworks\base\core\java\android\app\ActivityThread.$H
public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case BIND_SERVICE:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");handleBindService((BindServiceData)msg.obj);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}}
这里又将Service的创建工作交给H的外部类ActivityThread的handleBindService()函数来完成。
frameworks\base\core\java\android\app\ActivityThread.java
private void handleBindService(BindServiceData data) {//data.token为Service在AMS中的ServiceRecordService s = mServices.get(data.token);if (DEBUG_SERVICE)Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);if (s != null) {try {data.intent.setExtrasClassLoader(s.getClassLoader());try {//是否重新绑定if (!data.rebind) {//回调Service的onBind函数IBinder binder = s.onBind(data.intent);//AMS回调ServiceConnection的connected函数ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);} else {//回调Service的onRebind函数s.onRebind(data.intent);ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, 0, 0, 0);}ensureJitEnabled();} catch (RemoteException ex) {}} catch (Exception e) {if (!mInstrumentation.onException(s, e)) {throw new RuntimeException("Unable to bind to service " + s+ " with " + data.intent + ": " + e.toString(), e);}}}}
在该函数里,Service运行的应用程序进程调用Service的onBind函数。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {// Refuse possible leaked file descriptorsif (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");}ServiceRecord r = (ServiceRecord)token;final long origId = Binder.clearCallingIdentity();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;if (r.connections.size() > 0) {Iterator<ArrayList<ConnectionRecord>> it= r.connections.values().iterator();while (it.hasNext()) {ArrayList<ConnectionRecord> clist = it.next();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);} catch (Exception e) {Slog.w(TAG, "Failure sending service " + r.name +  " to connection " + c.conn.asBinder() +  " (in " + c.binding.client.processName + ")", e);}}}}}serviceDoneExecutingLocked(r, mStoppingServices.contains(r));Binder.restoreCallingIdentity(origId);}}}

Service启动过程


frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
private final void sendServiceArgsLocked(ServiceRecord r,boolean oomAdjusted) {final int N = r.pendingStarts.size();if (N == 0) {return;}//遍历Service启动参数列表while (r.pendingStarts.size() > 0) {try {//对参数列表中的每一项StartItem都启动一次ServiceServiceRecord.StartItem si = r.pendingStarts.remove(0);if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "+ r + " " + r.intent + " args=" + si.intent);if (si.intent == null && N > 1) {// If somehow we got a dummy null intent in the middle,// then skip it.  DO NOT skip a null intent when it is// the only one in the list -- this is to support the// onStartCommand(null) case.continue;}//设置投递时间si.deliveredTime = SystemClock.uptimeMillis();//将已投递参数项保存到deliveredStarts列表中r.deliveredStarts.add(si);si.deliveryCount++;if (si.neededGrants != null) {grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,si.getUriPermissionsLocked());}bumpServiceExecutingLocked(r, "start");if (!oomAdjusted) {oomAdjusted = true;updateOomAdjLocked(r.app);}int flags = 0;if (si.deliveryCount > 1) {flags |= Service.START_FLAG_RETRY;}if (si.doneExecutingCount > 0) {flags |= Service.START_FLAG_REDELIVERY;}//RPC调用Service运行进程的scheduleServiceArgs函数启动Service服务r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);} catch (RemoteException e) {// Remote process gone...  we'll let the normal cleanup take// care of this.if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);break;} catch (Exception e) {Slog.w(TAG, "Unexpected exception", e);break;}}}
和上面Service创建及绑定过程类似,这里仍然是通过Binder跨进程函数调用方式调用Service运行进程中的ApplicationThread Binder本地对象的scheduleServiceArgs()函数来启动Service
frameworks\base\core\java\android\app\ActivityThread.$ApplicationThread
public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,int flags ,Intent args) {ServiceArgsData s = new ServiceArgsData();s.token = token;s.taskRemoved = taskRemoved;s.startId = startId;s.flags = flags;s.args = args;queueOrSendMessage(H.SERVICE_ARGS, s);}
将RPC函数调用转换为应用程序进程中的异步调用
frameworks\base\core\java\android\app\ActivityThread.$H
public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case SERVICE_ARGS:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");handleServiceArgs((ServiceArgsData)msg.obj);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}}
该函数直接调用ActivityThread类的handleServiceArgs()函数来启动Service
frameworks\base\core\java\android\app\ActivityThread.java
private void handleServiceArgs(ServiceArgsData data) {Service s = mServices.get(data.token);if (s != null) {try {if (data.args != null) {data.args.setExtrasClassLoader(s.getClassLoader());}int res;if (!data.taskRemoved) {//回调Service的onStartCommand函数res = s.onStartCommand(data.args, data.flags, data.startId);} else {s.onTaskRemoved(data.args);res = Service.START_TASK_REMOVED_COMPLETE;}QueuedWork.waitToFinish();try {//通知ActivityManagerService服务Service启动完成ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, 1, data.startId, res);} catch (RemoteException e) {// nothing to do.}ensureJitEnabled();} catch (Exception e) {if (!mInstrumentation.onException(s, e)) {throw new RuntimeException("Unable to start service " + s+ " with " + data.args + ": " + e.toString(), e);}}}}


本文完整介绍了Service的创建启动过程,无论是Service的创建还是启动,Android应用程序进程自身都无法完成,必须通过ActivityManagerService服务调度实现,只有在ActivityManagerService服务端备案后,由ActivityManagerService服务通知应用程序进程来创建并启动Service。


原创粉丝点击