Android - Service 启动过程 概述 Service 启动过程与 Activity 启动过程比较相似,不了解 Activity 启动过程的可以先看一下:Activity 启动过程 。
Service 的启动分两种情况:startService,bindService。
startService 通常情况我们在调用 startService 启动 Service 是运行在 App 进程中的。下面主要讨论下运行在单独进程中的情况。
在 AndroidManifest 文件中把 Service 配置 android:process 上属性,Service 就可以启动在单独进程中了。
首先要明白一个问题,在 Activity 中使用的 startService 方法是定义在 Context 的抽象类中,它的真正实现者是 ContextImpl,所以我们首先进入 ContextImpl 类。
ContextImpl.startService()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override public ComponentName startService (Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, mUser); } private ComponentName startServiceCommon (Intent service, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault(). startService(mMainThread.getApplicationThread(), service,service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); return cn; } catch (RemoteException e) { return null ; } }
从 ContextImpl 类的 startService 开始,然后进入本类的 startServiceCommon 方法,并最终调用 ActivityManagerNative.getDefault() 对象的 startService 方法。其实这里的 ActivityManagerNative.getDefault() 就是 ActivityManagerProxy 对象。这里涉及到 Binder 相关知识,不了解的请看:Binder 机制 。
ActivityManagerProxy.startService()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public ComponentName startService (IApplicationThread caller, Intent service, String resolvedType, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null ); service.writeToParcel(data, 0 ); data.writeString(resolvedType); data.writeInt(userId); mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0 ); reply.readException(); ComponentName res = ComponentName.readFromParcel(reply); data.recycle(); reply.recycle(); return res; }
通过 Binder 调用 ActivityManagerNative 类中 onTransact 方法,其识别码为 START_SERVICE_TRANSACTION,并最终调用 ActivityManagerNative 的实现类 ActivityManagerService 的 startService 方法。
ActivityManagerService.startService()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Override public ComponentName startService (IApplicationThread caller, Intent service, String resolvedType, int userId) { enforceNotIsolatedCaller("startService" ); 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, userId); Binder.restoreCallingIdentity(origId); return res; } }
在这里调用 mServices 对象的 startServiceLocked 方法,这里的 mServices 对象是 ActiveServices 类。
ActiveServices.startServiceLocked()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ComponentName startServiceLocked (IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, int userId) { ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPid, callingUid, userId, true , callerFg); ServiceRecord r = res.record; return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); } ComponentName startServiceInnerLocked (ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) { synchronized (r.stats.getBatteryStats()) { r.stats.startRunningLocked(); } String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false ); }
首先通过 retrieveServiceLocked 方法来解析 service 这个 Intent,就是解析前面我们在 AndroidManifest.xml 定义的 Service 标签的 intent-filter 相关内容,然后将解析结果放在 res.record 中,再调用 startServiceInnerLocked 方法。startServiceInnerLocked 方法中会调用 bringUpServiceLocked 方法。
ActiveServices.bringUpServiceLocked()
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 private final String bringUpServiceLocked (ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) { if (app != null && app.thread != null ) { try { app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null ; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); } } if (app == null ) { if ((app=mAm.startProcessLocked(procName, r.appInfo, true , intentFlags, "service" , r.name, false , isolated, false )) == null ) { bringDownServiceLocked(r); return msg; } if (isolated) { r.isolatedProc = app; } } if (!mPendingServices.contains(r)) { mPendingServices.add(r); } }
这个方法比较重要,这里有两种选择,当 Service 所在的进程存在时,将调用realStartServiceLocked 方法来启动 Service,否则的话调用 startProcessLocked 方法来启动新进程。
ActivityManagerService.startProcessLocked()
1 2 3 4 5 6 7 8 9 10 11 12 13 private final void startProcessLocked (ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { boolean isActivityProcess = (entryPoint == null ); if (entryPoint == null ) entryPoint = "android.app.ActivityThread" ; checkTime(startTime, "startProcess: asking zygote to start proc" ); Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs); }
这里通过 Process 的 start 方法启动 ActivityThread 的新进程,我们进入该类的 main 方法。
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 public static void main (String[] args) { Process.setArgV0("<pre-initialized>" ); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false ); if (sMainThreadHandler == null ) { sMainThreadHandler = thread.getHandler(); } if (false ) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread" )); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited" ); } private void attach (boolean system) { final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { } }
在 Android 应用程序中,每一个进程对应一个 ActivityThread 实例,然后这里创建了 ActivityThread 对象并调用了其 attach 方法,在 attach 方法中又调用了 ActivityManagerProxy.attachApplication 方法。
ActivityManagerProxy.attachApplication()
1 2 3 4 5 6 7 8 9 10 public void attachApplication (IApplicationThread app) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(app.asBinder()); mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0 ); reply.readException(); data.recycle(); reply.recycle(); }
通过 Binder 机制会调用 ActivityManagerNative 中的 onTransact 方法,其识别码为 ATTACH_APPLICATION_TRANSACTION,并最终调用 ActivityManagerService 中的 attachApplication 方法。
ActivityManagerService.attachApplication()
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 @Override public final void attachApplication (IApplicationThread thread) { synchronized (this ) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } } private final boolean attachApplicationLocked (IApplicationThread thread, int pid) { if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true ; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true ; } } if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true ; } } }
这里如果是启动 Service 将调用 ActiveServices 对象的 attachApplicationLocked 方法,而如果是启动 Activity 将调用 ActivityStackSupervisor 对象的 attachApplicationLocked 方法。
ActiveServices.attachApplicationLocked() -> realStartServiceLocked()
1 2 3 4 5 6 7 8 9 10 11 12 13 private final void realStartServiceLocked (ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { if (app.thread == null ) { throw new RemoteException(); } app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); }
此处的 app.thread 是一个 IApplicationThread 对象,而 IApplicationThread 的代理类是 ApplicationThreadProxy,我们进入 app.thread 对象的 scheduleCreateService 方法。
ApplicationThreadProxy.scheduleCreateService()
1 2 3 4 5 6 7 8 9 10 11 12 13 public final void scheduleCreateService (IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); info.writeToParcel(data, 0 ); compatInfo.writeToParcel(data, 0 ); data.writeInt(processState); mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null , IBinder.FLAG_ONEWAY); data.recycle(); }
通过 Binder 对象调用 ApplicationThreadNative 的 onTransact 方法,在其方法中调用子类的 scheduleCreateService 方法,即最终调用 ApplicationThreadNative 的子类 ApplicationThread 的 scheduleCreateService 方法。
ApplicationThread.scheduleCreateService()
1 2 3 4 5 6 7 8 9 10 11 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 发送 Message 来处理该操作,并进入到 H 的 handleMessage 方法中,其识别码为 CREATE_SERVICE。
1 2 3 4 5 6 7 8 9 private class H extends Handler { public void handleMessage (Message msg) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate" ); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }
ApplicationThread.handleCreateService()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private void handleCreateService (CreateServiceData data) { Service service = null ; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { } 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); }
处通过类加载器 ClassLoader 来加载 Service 对象,此处的 data.info.name 就是我们要启动的 Service,加载完成后需要将其强转换为 Service 对象,也就是说我们的 Service 必须要继承于 Service 基类。
处这里先创建一个 ContextImpl 对象,每个 Activity 和 Service 都有一个 Context 对象。
处这里调用 Service 的 onCreate 方法。
bindService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void test () { Intent intent = new Intent(this , XXXService.class); bindService(intent, conn, BIND_AUTO_CREATE); } private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected (ComponentName name, IBinder service) { ... } @Override public void onServiceDisconnected (ComponentName name) { ... } }
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 @Override public boolean bindService (Intent service, ServiceConnection conn, int flags) { return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), Process.myUserHandle()); } private boolean bindServiceCommon (Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) { IServiceConnection sd; if (mPackageInfo != null ) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } validateServiceIntent(service); try { IBinder token = getActivityToken(); ... int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); return res != 0 ; } }
LoadedApk 对象是 Apk 文件在内存中的表示。 Apk 文件的相关信息,诸如 Apk 文件的代码和资源,甚至代码里面的 Activity,Service 等组件的信息我们都可以通过此对象获取。
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 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 ) { sd = map.get(c); } if (sd == null ) { sd = new ServiceDispatcher(c, context, handler, flags); if (map == null ) { map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } return sd.getIServiceConnection(); } }
ActivityManagerService.bindService()
1 2 3 4 5 6 7 8 9 10 11 public int bindService (IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException { synchronized (this ) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
ActiveServices.bindServiceLocked() -> 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 private final void realStartServiceLocked (ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { try { app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); } requestServiceBindingLocked(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 ); } private final boolean requestServiceBindingLocked (ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { if ((!i.requested || rebind) && i.apps.size() > 0 ) { try { r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); } } return true ; }
ApplicationThread.scheduleBindService()
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 handleBindService (BindServiceData data) { Service s = mServices.get(data.token); if (s != null ) { try { if (!data.rebind) { IBinder binder = s.onBind(data.intent); ActivityManagerNative.getDefault() .publishService(data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManagerNative.getDefault() .serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0 , 0 ); } ensureJitEnabled(); } ... } }
调用 ApplicationThread 的 scheduleBindService,scheduleBindService 通过 mH 发送一个 H.BIND_SERVICE 消息,mH 收到该消息调用 handleBindService(BindServiceData data)。
总结
使用这种 start 方式启动的 Service 的生命周期如下: onCreate() -> onStartCommand()(onStart()方法已过时) -> onDestory()
说明:如果服务已经开启,不会重复的执行 onCreate(), 而是会调用 onStart() 和onStartCommand()。 服务停止的时候调用 onDestory()。服务只会被停止一次。
特点:一旦服务开启跟调用者(开启者)就没有任何关系了。 开启者退出了,开启者挂了,服务还在后台长期的运行。 开启者不能调用服务里面的方法。
使用这种 start 方式启动的 Service 的生命周期如下: onCreate() -> onBind() -> onUnbind() -> onDestory()
注意:绑定服务不会调用 onStart() 或者 onStartCommand() 方法
特点:bind 的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。 绑定者可以调用服务里面的方法。
参考资料
扫一扫关注我的公众账号