《Android开发艺术探索》9.3章Service
分为两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定态,主要用于其他组件和Service
的交互。需要注意的是,Service
的这两种状态是可以共存的,即Service
既可以处于启动状态也可以同时处于绑定状态。 通过Context
的startService
方法即可启动一个Service
:
1 2 Intent intent = new Intent (content,Service.class); startService(intent);
通过Context
的bindService
方法可以绑定一个Service
:
1 2 Intent intent = new Intent (content,Service.class); bindService(intent,connection,BIND_AUTO_CREATE);
Service启动过程 Service
的启动时从ContextWrapper
的startService
开始的:
1 2 3 4 @Override public ComponentName startService (Intent service) { return mBase.startService(service); }
mBase
是Context
的实现类ContextImpl
,在Activity
启动的时候会通过attach
方法关联一个ContextImpl
,这个ContextImpl
就是上面的mBase
,从ContextWrapper
的实现来看,大部分的实现都是通过mBase
来实现的,这是一种典型的桥接模式。在ContextImpl
的startService
方法中又调用了startServiceCommon
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Override public ComponentName startService (Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false , mUser); }private ComponentName startServiceCommon (Intent service, boolean requireForeground,UserHandle user) { validateServiceIntent(service); service.prepareToLeaveProcess(this ); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier()); return cn; }
在startServiceCommon
中通过getService
这个对象来启动一个服务,这个对象就是AMS,需要注意的是,在上述代码中通过AMS来启动服务的过程是一个跨进程调用。AMS的startService
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override public ComponentName startService (IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws TransactionTooLargeException { synchronized (this ) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; } }
AMS会通过mServices
来完成service
的启动过程,mServices
的对象类型是ActiveServices
,ActiveServices
是一个辅助AMS进行Service
管理的类,包括Service
的启动、绑定和停止。在startService
方法的尾部会调用startServiceInnerLocked
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 ComponentName startServiceInnerLocked (ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { 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(); } String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false , false ); return r.name; }
上述代码中ServiceRecord
是描述一个Service记录,ServiceRecord
一直贯穿整个Service流程,startServiceInnerLocked
并没有完成启动Service的完整流程,而是将后续的过程交给了bringUpServiceLocked
,在该方法中又调用了realStartServiceLocked
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 private final void realStartServiceLocked (ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { r.app = app; r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); final boolean newService = app.services.add(r); bumpServiceExecutingLocked(r, execInFg, "create" ); mAm.updateLruProcessLocked(app, false , null ); mAm.updateOomAdjLocked(); boolean created = false ; try { synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_SERVICE); app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true ; } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app); throw e; } finally { if (!created) { final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); if (newService) { app.services.remove(r); r.app = null ; } if (!inDestroying) { scheduleServiceRestartLocked(r, false ); } } } if (r.whitelistManager) { app.whitelistManager = true ; } requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null , true ); 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 ); if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r); getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false ; } if (r.delayedStop) { r.delayedStop = false ; if (r.startRequested) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Applying delayed stop (from start): " + r); stopServiceLocked(r); } } }
在realStartServiceLocked
方法中,首先通过app.thread
的scheduleCreateService
方法来创建Service
对象并调用其onCreate
,接着再通过sendServiceArgsLocked
方法来调用Service
的其他方法,比如onStartCommand
,这两个过程均是进程间通信。app.thread
对象是IApplicationThread
类型,它实际上是一个Binder
,它的具体实现是ApplicationThread
和ApplicationThreadNative
。由于ApplicationThread
继承了ApplicationThreadNative
,因此只需要看ApplicationThread
对Service
启动过程的处理即可,这对应着它的scheduleCreateService
方法,如下所示:
1 2 3 4 5 6 7 8 9 10 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; sendMessage(H.CREATE_SERVICE, s); }
通过发送消息给Handler H
来完成的。H会接收这个CREATE_ SERVICE
消息并通过ActivityThread
的handleCreateService
方法来完成Service的最终启动,handleCreateService
的源码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private void handleCreateService (CreateServiceData data) { unscheduleGcIdler(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null ; java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); ContextImpl context = ContextImpl.createAppContext(this , packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false , mInstrumentation); service.attach(context, this , data.info.name, data.token, app, ActivityManagerNative.getDefault()); service.onCreate(); mServices.put(data.token, service); ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0 , 0 ); }
handleCreateService
主要完成了以下几件事: 首先通过类加载器创建了Service实例,接着创建ContextImpl
对象和Application
对象 并通过service.attach方法建立联系,最后调用service.onCreate
方法,并将service
存储在ActivityThread
中的一个列表mServices
中
1 final ArrayMap<IBinder, Service> mServices = new ArrayMap <>();
由于service
的onCreate
方法执行了,也就意味着Service
已经启动了。除此之外,ActivityThead
中还会通过handleServiceArgs
方法调用Service
的onStartCommand
方法。
Service绑定过程 和启动过程一样,也是从ContextWrapper
开始的:
1 2 3 4 5 @Override public boolean bindService (Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); }
然后是ContextImpl
的bindService
方法调用bindServiceCommon
方法,然后远程调用AMS的bindService
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 private boolean bindServiceCommon (Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) { IServiceConnection sd; if (conn == null ) { throw new IllegalArgumentException ("connection is null" ); } if (mPackageInfo != null ) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } else { throw new RuntimeException ("Not supported in system context" ); } validateServiceIntent(service); try { IBinder token = getActivityToken(); if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null && mPackageInfo.getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { flags |= BIND_WAIVE_PRIORITY; } service.prepareToLeaveProcess(this ); int res = ActivityManager.getService().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); if (res < 0 ) { throw new SecurityException ( "Not allowed to bind to service " + service); } return res != 0 ; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
在该方法中,首先将客户端的ServiceConnection
转化为ServiceDispatcher.InnerConnection
对象,因为服务绑定是跨进程的,所以ServiceConnection
对象必须借助Binder
对象才能让远程服务端调用自己的方法。ServiceDispatcher
起着连接ServiceConnection
和InnerConnection
的作用。这个过程由LoadedApk.getServiceDispatcher
方法完成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public final IServiceConnection getServiceDispatcher (ServiceConnection c, Context context, Handler handler, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null ; ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); if (map != null ) { if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c); sd = map.get(c); } if (sd == null ) { sd = new ServiceDispatcher (c, context, handler, flags); if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); if (map == null ) { map = new ArrayMap <>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } return sd.getIServiceConnection(); } }
在上面的代码中,mServices
是一个ArrayMap
,它存储了一个应用当前活动的ServiceConnection
和ServiceDispatcher
的映射关系,其声明如下:
1 2 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices = new ArrayMap <>();
系统首先会查找是否存在相同的ServiceConnection
,如果不存在就重新创建一个ServiceDispatcher
对象,并将其存储在mServices
中,其中映射关系的key是ServiceConnection
,value是ServiceDispatcher
,在ServiceDispatcher
的内部又保存了ServiceConnection
和InnerConnection
对象。当Service
和客户端建立连接后,系统会通过InnerConnection
来调用ServiceConnection
中的onServiceConnected
方法,这个过程有可能是跨进程的。当ServiceDispatcher
创建好了以后,getServiceDispatcher
会 返回其保存的InnerConnection
对象。 接着调用AMS的bindService
方法,该方法又调用了bindServiceLocked
–>bringUpServiceLocked
–>realStartServiceLocked
,这个过程和上面的StartService
过程逻辑类似,最终都是通过ApplicationThread
来完成Service
的实例创建并调用onCreate
方法。和启动Service
过程不同的是,绑定过程会调用app.thread
的scheduleBindService
方法,这个过程的实现在ActivityService
的requestServiceBindingsLocked
方法中:
1 2 3 4 5 6 7 8 9 10 private final void requestServiceBindingsLocked (ServiceRecord r, boolean execInFg) throws TransactionTooLargeException { for (int i=r.bindings.size()-1 ; i>=0 ; i--) { IntentBindRecord ibr = r.bindings.valueAt(i); if (!requestServiceBindingLocked(r, ibr, execInFg, false )) { break ; } } }
该方法用到了r.bindings
。它是一个ArrayMap
,保存了客户端的bind
消息:
1 final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings = new ArrayMap <Intent.FilterComparison, IntentBindRecord>();
具体保存方法在AMS一开始的方法bindServiceLocked
中:
1 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
在requestServiceBindingsLocked
方法中调用了了requestServiceBindingLocked
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 private final boolean requestServiceBindingLocked (ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { if (r.app == null || r.app.thread == null ) { return false ; } if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested + " rebind=" + rebind); if ((!i.requested || rebind) && i.apps.size() > 0 ) { try { bumpServiceExecutingLocked(r, execInFg, "bind" ); r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); if (!rebind) { i.requested = true ; } i.hasBound = true ; i.doRebind = false ; } catch (TransactionTooLargeException e) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e); final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); throw e; } catch (RemoteException e) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r); final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); return false ; } } return true ; }
在上述代码中,app.thread
这个对象多次出现过,它实际上就是ApplicationThread
。ApplicationThread
的一系列以schedule
开头的方法,其内部都是通过Handler H
来中转的,对于scheduleBindService
方法来说也是如此,它的实现如下所示:
1 2 3 4 5 6 7 8 9 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; sendMessage(H.BIND_SERVICE, s); }
在H内部,接收到BIND_SERVICE
这类消息时,会交给ActivityThread
的handleBindService
方法来处理。在handleBindService
中,首先根据Service
的token
取出Service
对象,然后调用Service
的onBind
方法,Service
的onBind
方法会返回一个Binder
对象给客户端使用,原则上来说,Service
的onBind
方法被调用以后,Service
就处于绑定状态了,但是onBind
方法是Service
的方法,这个时候客户端并不知道已经成功连接Service
了,所以还必须调用客户端的ServiceConnection
中的onServiceConnected
,这个过程是由ActivityManager.getService()
的publishService
方法来完成的,而前面多次提到,ActivityManager.getService()
就是AMS。handleBindService
的实现过程如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 private void handleBindService (BindServiceData data) { Service s = mServices.get(data.token); if (s != null ) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (!data.rebind) { IBinder binder = s.onBind(data.intent); ActivityManager.getService().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0 , 0 ); } ensureJitEnabled(); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } 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时,Service的onBind
方法只会执行一次 ,除非Service被终止了。当Service的onBind执行以后,系统还需要告知客户端已经成功连接Service了。根据上面的分析,这个过程由AMS的publishService
方法来实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 public void publishService (IBinder token, Intent intent, IBinder service) { if (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" ); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }
从_上面代码可以看出,AMS的publishService
方法将具体的工作交给了ActiveServices
类型的mServices
对象来处理。ActiveServices
的publishServiceLocked
方法看起来很复杂,但其实核心代码就只有一- 句话: c.conn.connected(r.name,service)
, 其中c的类型是ConnectionRecord
,c.comn
的类型是ServiceDispatcher.InnerConnection
, service就是Service的onBind方法返回的Binder对象。为了分析具体的逻辑,下面看一下ServiceDispatcher.InnerConnection
的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private static class InnerConnection extends IServiceConnection .Stub { 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); } } }
从InnerConnection
的定义可以看出来,它的connected
方法又调用了ServiceDispatcher
的connected
方法
1 2 3 4 5 6 7 public void connected (ComponentName name, IBinder service, boolean dead) { if (mActivityThread != null ) { mActivityThread.post(new RunConnection (name, service, 0 , dead)); } else { doConnected(name, service, dead); } }
对于Service的绑定过程来讲,ServiceDispatcher
中的mActivityThread
就是一个handler
,它就是ActivityThread
中的H
,从Service
的创建过程来讲,mActivityTHread
不会为null
,这样一来,RunConnection
就可以经由H
的post
方法从而运行在主线程中,因此,客户端的ServiceConnection
中的方法回调是在主线程中执行的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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; }
很显然,RunConnection
的run
方法也是简单调用了ServiceDispatcher
的doConnected
方法,由于ServiceDispatcher
内部保存了客户端的ServiceConnection
对象,因此它可以很方便地调用ServiceConnection
对象的onServiceConnected
方法,如下所示。 至此,bindService的过程完成。
以上