Android启动Service流程
来源:互联网 发布:603258电魂网络吧 编辑:程序博客网 时间:2024/05/25 23:25
其实启动Service和我们上一篇启动App的流程差不多,通过学习老罗的Android系统在新进程中启动自定义服务过程(startService)的原理分析,补充了一些不太清楚的知识点。这里做一下笔记。
老罗的例子,Service是设置了一个android:process属性,表明要在新建的进程运行Service。例子xml代码:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="shy.luo.ashmem" android:sharedUserId="android.uid.system" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> ...... <service android:enabled="true" android:name=".Server" android:process=".Server" ><!-- 设置了process属性 --> <intent-filter> <action android:name="shy.luo.ashmem.server"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service> </application> </manifest>
在这篇博文中,讲述了ActivityManagerService是在一个ServerThread类(有种熟悉的感觉,ActivityThread,不过没有联系的,哈哈)中启动的,代码如下:
class ServerThread extends Thread { ...... @Override public void run() { ...... // Critical services... try { ...... context = ActivityManagerService.main(factoryTest); ...... ActivityManagerService.setSystemProcess(); ...... } catch (RuntimeException e) { Slog.e("System", "Failure starting core service", e); } ...... } ......}
调用了ActivityManagerService的main和setSystemProcess方法,我们接着看代码:
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... static ActivityManagerService mSelf; ...... public static void setSystemProcess() { try { ActivityManagerService m = mSelf; ServiceManager.addService("activity", m); ...... } catch (PackageManager.NameNotFoundException e) { ...... } } ...... public static final Context main(int factoryTest) { ...... ActivityManagerService m = thr.mService; mSelf = m; ...... } }
在setSystemProcess方法里,调用了ServiceManager的addService方法,这样ActivityManagerService作为Service注册到ServiceManager中,Client就可以在ServiceManager中获取到ActivityManagerService的代理对象,并与之通信。这样ActivityManagerService就算是“启动”起来了。
当我们通过startService启动Service时,和启动App一样,其实是调用ActivityManagerService代理对象ActivityManagerProxy 的startService方法:
class ActivityManagerProxy implements IActivityManager { ...... public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType) 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); mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); ComponentName res = ComponentName.readFromParcel(reply); data.recycle(); reply.recycle(); return res; } ...... }
参数service是一个Intent实例,它里面指定了要启动的服务的名称,也就是例子定义的服务名称“shy.luo.ashmem.server”了。
参数caller是一个IApplicationThread实例,它是一个在主进程创建的一个Binder对象。在Android应用程序中,每一个进程都用一个ActivityThread实例来表示,而在ActivityThread类中,有一个成员变量mAppThread,它是一个ApplicationThread实例,实现了IApplicationThread接口,它的作用是用来辅助ActivityThread类来执行一些操作(其实mAppThread是ActivityManagerService持有与App进程通信的Binder代理对象,ActivityManagerService利用调用IApplicationThread代理对象,实现通知ActivityThread执行对应的方法),这个我们在后面会看到它是如何用来启动服务的。
参数resolvedType是一个字符串,它表示service这个Intent的MIME类型,它是在解析Intent时用到的。在这个例子中,我们没有指定这个Intent 的MIME类型,因此,这个参数为null。
ActivityManagerProxy类的startService函数把这三个参数写入到data本地变量去,接着通过mRemote.transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒正在等待Client请求的ActivityManagerService进程,最后进入到ActivityManagerService的startService函数中。
接下来就是ActivityManagerService会做一系列检查,然后通过socket方式通知Zygote孵化新的进程,指定新的进程加载ActivityThread类,并执行main方法。代码过程请参考我上一篇博文Android应用App启动流程。这里我们还是着重看一下Service在新的进程启动过程。
先看看ActivityThread的main方法:
public final class ActivityThread { ...... public static final void main(String[] args) { ...... Looper.prepareMainLooper(); ...... ActivityThread thread = new ActivityThread(); thread.attach(false); ...... Looper.loop(); ...... thread.detach(); ...... } }
因为这段代码可以带我们了解App的启动和初始化过程,所以很重要。在这里初始化Looper,创建Looper和MessageQueue,然后调用attach方法,把自己的ApplicationThread代理对象通过IPC传给ActivityManagerService,调用Looper.loop方法,让Looper不断的从MessageQueue取出消息,实现消息机制。我们来看看attach方法(上一个博文没有写清楚attach方法,因为不清楚):
public final class ActivityThread { ...... private final void attach(boolean system) { ...... if (!system) { ...... IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { } } else { ...... } ...... } ...... }
主要是调用ActivityManagerService的代理对象ActivityManagerProxy的attachApplication的方法:
class ActivityManagerProxy implements IActivityManager { ...... 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(); } ...... }
这下应该清楚知道ActivityThread怎么把ApplicationThread的代理对象传给ActivityManagerService了吧。我们顺便往下看,ActivityManagerService调用attachApplication的方法:
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } } ...... }
attachApplicationLocked方法代码:
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { // Find the application record that is being attached... either via // the pid if we are running in multiple processes, or just pull the // next app record if we are emulating process with anonymous threads. ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } else if (mStartingProcesses.size() > 0) { app = mStartingProcesses.remove(0); app.setPid(pid); } else { app = null; } ...... String processName = app.processName; ...... app.thread = thread; ...... boolean badApp = false; ...... // Find any services that should be running in this process... if (!badApp && mPendingServices.size() > 0) { ServiceRecord sr = null; try { for (int i=0; i<mPendingServices.size(); i++) { sr = mPendingServices.get(i); if (app.info.uid != sr.appInfo.uid || !processName.equals(sr.processName)) { continue; } mPendingServices.remove(i); i--; realStartServiceLocked(sr, app); didSomething = true; } } catch (Exception e) { ...... } } ...... return true; } ...... }
最终调用realStartServiceLocked方法:
class ActivityManagerProxy implements IActivityManager { ...... private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app) throws RemoteException { ...... r.app = app; ...... try { ...... app.thread.scheduleCreateService(r, r.serviceInfo); ...... } finally { ...... } ...... } ...... }
这里的app.thread是一个ApplicationThread的代理对象,通过调用这个代理对象scheduleCreateService方法,通知ActivityThread启动Service,回到App进程。
class ApplicationThreadProxy implements IApplicationThread { ...... public final void scheduleCreateService(IBinder token, ServiceInfo info) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); info.writeToParcel(data, 0); mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } ...... }
public final class ActivityThread { ...... private final class ApplicationThread extends ApplicationThreadNative { ...... public final void scheduleCreateService(IBinder token, ServiceInfo info) { CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; queueOrSendMessage(H.CREATE_SERVICE, s); } ...... } ...... }
又见到熟悉的身形了,ApplicationThread作为ActivityThread内部类,直接代用queueOrSendMessage方法,分发消息到ActivityThread的MessageQueue,通知ActivityThread执行对应方法。所以整个Handler的消息机制,在Android中起了大多的作用。整个App运行,都是通过这个消息机制得以和谐运行,表示不禁感叹。上次都没看怎么ApplicationThread怎么分发消息,代码如下:
public final class ActivityThread { ...... private final void queueOrSendMessage(int what, Object obj) { queueOrSendMessage(what, obj, 0, 0); } private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { synchronized (this) { ...... Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; mH.sendMessage(msg); } } ...... }
很普通代码,通过Handler分发消息。看一下ActivityThread的Handler怎么处理启动Service的代码:
public final class ActivityThread { ...... private final class H extends Handler { ...... public void handleMessage(Message msg) { ...... switch (msg.what) { ...... case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); break; ...... } ...... } ...... } ...... }
调用了handleCreateService方法:
public final class ActivityThread { ...... private final 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(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo); 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); ContextImpl context = new ContextImpl(); context.init(packageInfo, null, this); Application app = packageInfo.makeApplication(false, mInstrumentation); context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); service.onCreate(); mServices.put(data.token, service); try { 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类,并执行service.onCreate()方法。至此,启动Service代码分析完毕。跟着老罗的代码解析,的确学习了不少。
参考资料
Android系统在新进程中启动自定义服务过程(startService)的原理分析
- Android启动Service流程
- Android service启动流程分析.
- android四大组件启动流程 - Service启动流程
- Android中Service的启动流程
- 《Android中级工程师》Service启动流程
- Service启动流程
- Service启动流程-startService
- Android启动流程分析(九) 解析init.rc的service
- Android Service的启动流程源码分析(8.0)
- Service 启动和绑定流程
- 系统Service的启动流程
- Service 启动流程源码解析
- Service的启动流程分析
- Android启动流程分析(十) action的执行和service的启动
- Android启动流程分析- action的执行和service的启动
- Android Service: 启动service, 停止service
- Android开机启动Service
- Android Service 自动启动
- python 的逻辑关系
- CSS中的相对定位和绝对定位
- git与github做版本控制
- mysql添加外键失败:sql 1452 Cannot add or update a child row:a foreign key constraint fails
- 【node.js学习之路】什么是Node.js?
- Android启动Service流程
- 金额小数点后面和前面字体大小不一致的实现
- ShareSDK 微信分享失败问题的解决
- ios NSURLSession使用说明及后台工作流程分析
- 国际化程序
- 导入kotlin-for-android-developers weather app项目遇到的坑
- 设计模式(04)创建者模式
- app-release-unsigned.apk is not signed
- 使用Eureka, Ribbon, Feign实现REST服务客户端