《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的过程完成。
以上