意思-(Android Framework(八))- Service

zydadmin2023-08-19  110

1,挂载文件系统,创建文件目录 调用selinux_setup权限安全相关

2,初始化内存空间 初始化属性服务 创建Epoll 注册监听子进程重启异常操作等,对子进程进行线程守护

3,startPropertyServic 开启属性服务 进行监听

4,LoadBootScripts 加载init.rc文件 进行解析 调用do_class_start 文件开启service

5,Service::Start函数->fork子进程->并且执行app_process文件,开启了zygote

1,startVm函数注册jvm startReg函数注册jni环境唤起 Zygote.main

2,forkSystemServer

3,preload预加载class 系统资源

4,调用runSelectLoop函数循环等待客户端连接

5,有客户端的连接后调用processOne

6,根据请求的targetClass 执行Main函数

system_server是系统用来启动管理service的入口,比如我们常用的AMS、WMS、PMS等等都是它来创建的,system_server加载了framework-res.apk,接着调用startBootstrapServices、startCoreServices、startOtherServices开启了非常多的服务,以及开启了WatchDog监控service。

它是一个服务的提供者,可以让应用获取到系统的各种服务,还有Binder机制。ServiceManager是Android系统为开发者提供的一个服务大管家,当开机之后,由内核态进入用户态之后,会启动system_server进程,在该进程里面会对AMS,PKMS,PMS等等进行创建。然后添加到ServiceManager中。SystemServer算是一个大管家,他整合了系统的各种服务,监控着我们服务,管理服务的周期。而ServiceManager只有一个功能就是提供binder通信,让应用可以获取到系统提供的服务。

是Android特有的一种通信方式。Android Binder的前身是OpenBinder,后来在OpenBinder的基础上开发了Android Binder。

Android基于Linux所以支持Linux原生的IPC通信机制:共享内存、Pipe、Socket。Binder是Android特有的。

性能上:稳定性: 安全:

Binder : 一次拷贝 c/s架构 客户端和服务端 稳定 内核层校验系统来保证通信安全

共享内存:0次 不稳定会有同步问题和并发死锁问题 自定义协议

管道pipe:需要两次拷贝 单管道 效率低只能读或者只能写 自定义协议

Socket:两次拷贝 c/s架构 不好的地方消耗性能握手和挥手 自定义协议

它是由system_server开启的,通过LauncherModel进行IPC通信(Binder)调用PackageManagerService的queryIntentActivities获取到所有应用的信息,然后绑定数据源到RecyclerView中,而它的点击事件则是通过ItemClickHandler来进行分发的

AMS是如何开启应用进程的,首先我们从Launcher的点击开始,调用到Activity的startActivity函数,通过Instrumentation的execStartActivity经过两次IPC(1.通过ServiceManager获取到ATMS 2.调用ATMS的startActivity) 调用到AMS端在AMS端进行了一系列的信息处理,会判断进程是否存在,没有存在的话就会开启进程(通过Socket,给ZygoteServer发送信息),传入entryPoint为ActivityThread,通过Zygote来fork出来子进程(应用进程)调用ActivityThread.main,应用进程创建之后会调用到AMS,由AMS来attachApplication存储进程信息,然后告诉客户端,让客户端来创建Application,并在客户端创建成功之后 继续执行开启Activity的流程。客户端接收到AMS的数据之后会创建loadedApk,Instrumentation 以及Application调用attach(attachBaseContext),调用Instrumentation的callApplicationOncreate执行Application的Oncreate周期.

应用执行完Application的OnCreate之后 回到ATMS的attachApplication 接着调用 realStartActivityLocked 创建了ClientTransaction,设置callBack为LaunchActivityItem添加了stateRequest 为ResumeActivityItem,然后通过IApplicationThread 回到客户端执行这两个事务,调用了ActivityThread的scheduleTransaction 函数,调用executeCallBack 执行了LaunchActivityItem的execute 他会调用ActivityThread的 handleLaunchActivity,会创建Activity Context,通过Instrumentation.newActivity 反射创建Activity 并调用attach 绑定window 再通过Instrumentation的callActivityOnCreate执行Activity的onCreate,在Activity的onCreate中分发监听给ActivityLifecycleCallbacks。最后设置ActivityClientRecord的state为ON_CREATE。 接着执行executeLifecycleState,调用了cycleToPath,之前设置了state为ON_CREATE,所以会返回一个Int数组{2} 调用performLifecycleSequence会执行到ActivityThread的handleStartActivity分发ActivityLifecycleCallbacks,并且分发给Fragments,调用Instrumentation的callActivityOnStart 执行Activity的onStart并设置state为ON_START,接着执行ResumeActivityItem的execute,会调用到ActivityThread的handleResumeActivity,调用performResume 分发resume事件给ActivityLifecycleCallbacks,分发Fragments,调用Instrumentation的callActivityOnResume 执行Activity的onResume。 最后会调用ActivityClientRecord.activity.makeVisible 通过WindowManager 添加当前View 和 WMS(IPC) 通信 绘制UI,接着postResume 会执行 ATMS的activityresume 设置 AMS的Activity的状态。

Service是一种可以在后台执行长时间运行操作而不提供界面的应用组件。服务可以由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可以通过绑定到服务与之进行交互,甚至是执行进程之间的通信。

在源码中我们可以直接在Activity中调用startService,那就跟一下 看看它是如何开启Service的。

文件目录:/android/frameworks/base/core/java/android/content/ContextWrapper.java

在AMS这里会先检查Service是否可以执行(常驻内存、蓝牙、电源白名单允许直接启动服务),接着调用bringUpServiceLocked 判断是否需要隔离进程如果非隔离 就看是否已经启动进程 执行realStartServiceLocked,否则是隔离进程 直接开启新进程。我们没有设置隔离进程 所以我们会直接开启新进程,开启进程的过程在之前已经接触很多次了,我们直接跳过,开启成功之后会将ServiceRecord添加到mPendingServices中去。所以我们看看进程创建成功之后会如何开启Service。

进程创建之后,会调用AMS的attachApplication 接着处理service(ActiveService),之前创建之后会添加到mPendingServices中,现在继续处理调用realStartServiceLocked来开启Service,在开启的过程中会埋入一个炸弹(给Handler发送一个SERVICE_TIMEOUT_MSG) 如果超时未处理会弹出ANR,然后调用app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreate 把Service存入到mService中,调用AMS的serviceDoneExecuting进行炸弹的拆除。 然后再埋炸弹 调用app.thread.scheduleServiceArgs 调用service.onStart

这样Service就运行起来了。我们再看看Service的onStop。

还是回到ContextImpl

bindService和startService使用方式也不一样,在这里我使用的是隐式意图。需要传递ServiceConnection,它就是我们用来IPC通信的。

使用方法如上,而ServiceConnection只是一个接口,它是怎么进行IPC通信的呢? 在onServiceConnected 中 给我们的IBinder是什么呢?我们跟下源码 看看bindService是如何运转的。

首先ServiceConnection是无法跨进程通信的,所以在LoadedApk.java中帮我们封装了InnerConnection 它继承自Stub,也就是native层的JavaBBinder,然后通过bindIsolatedService将sd(InnerConnection)写入到Parcel中,调用AMS(BinderProxy)的transact进行IPC 通信,把InnerConnection存入到客户端的nodes中,以及给AMS的refs_by_node和refs_by_desc挂上InnerConnection 接着唤醒AMS,唤醒之后调用onTransact读取到传过来的sd并且包装成BpBinder(BinderProxy)返回,这样AMS就在bindIsolatedService的时候拿到了InnerConnection的BpBinder,接着AMS 通过pkms通过intent查找到服务端进程,创建AppBindRecord和ConnectionRecord,接着调用bringUpServiceLocked 看是否开启进程 如果没有开启就先开启进程,开启了进程之后 调用realStartServiceLocked 也埋了炸弹 接着调用 app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreate 把Service存入到mService中,调用serviceDoneExecutingLocked把炸弹拆除,再调用requestServiceBindingsLocked 去执行r.app.thread.scheduleBindService 执行服务端的onBind函数拿到了返回的Binder再调用AMS的publishService把服务发布到AMS(在服务端的进程创建binder_proc(server) 在AMS的refs_by_node 和refs_by_desc 挂上server),AMS的onTransact

中读取到服务端返回的server(Binder)包装成BpBinder,然后调用c.conn.connected(从refs_by_desc 和 refs_by_node 找到InnerConnection)调用connect 所以到了客户端进程会把server的BpBinder 挂在refs_by_desc和refs_by_node上边。 之后拆除炸弹

以上整体的流程就走完了,包括客户端进程如何存入InnerConnection的,AMS是如何存储InnerConnection的,以及服务端是怎么创建server的并且把server挂在AMS上的,以及AMS是如何把server给到客户端的。

我们可以从源码角度来阐述为什么start不执行onbind(bindingssize为0),而bindService(bindings有值)。bindService为什么不执行onStart

可以参考上边的两个图,最好再阐述下bindService的InnerConnection以及Binder是如何存储的,怎么执行的。

这里我们没有跟源码 简单说下吧 START_STICKY(Service被kill service会重启,不会保留之前传递过来的intent) START_NOT_STICKY(不会重启该Service) START_REDELIVER_INTENT(service 被杀死之后 重启 并且保留之前的intent)

例如视频中讲解的,优化进程的启动,提升用户体验。

startService会调用到ContextImpl的startService,它会直接调用AMS的startService。在AMS这里会先检查Service是否可以执行(常驻内存、蓝牙、电源白名单允许直接启动服务),接着调用bringUpServiceLocked 判断是否需要隔离进程如果非隔离 就看是否已经启动进程 执行realStartServiceLocked,否则是隔离进程 直接开启新进程。开启成功之后会将ServiceRecord添加到mPendingServices中去。进程创建之后,会调用AMS的attachApplication 接着处理service(ActiveService),之前创建之后会添加到mPendingServices中,现在继续处理调用realStartServiceLocked来开启Service,在开启的过程中会埋入一个炸弹(给Handler发送一个SERVICE_TIMEOUT_MSG) 如果超时未处理会弹出ANR,然后调用app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreate 把Service存入到mService中,调用AMS的serviceDoneExecuting进行炸弹的拆除。 然后再埋炸弹 调用app.thread.scheduleServiceArgs 调用service.onStart

stop的流程和start的流程差不多,需要注意的是stop只是从map中移除了,我们需要自己释放资源。

首先ServiceConnection是无法跨进程通信的,所以在LoadedApk.java中帮我们封装了InnerConnection 它继承自Stub,也就是native层的JavaBBinder,然后通过bindIsolatedService将sd(InnerConnection)写入到Parcel中,调用AMS(BinderProxy)的transact进行IPC 通信,把InnerConnection存入到客户端的nodes中,以及给AMS的refs_by_node和refs_by_desc挂上InnerConnection 接着唤醒AMS,唤醒之后调用onTransact读取到传过来的sd并且包装成BpBinder(BinderProxy)返回,这样AMS就在bindIsolatedService的时候拿到了InnerConnection的BpBinder,接着AMS 通过pkms通过intent查找到服务端进程,创建AppBindRecord和ConnectionRecord,接着调用bringUpServiceLocked 看是否开启进程 如果没有开启就先开启进程,开启了进程之后 调用realStartServiceLocked 也埋了炸弹 接着调用 app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreate 把Service存入到mService中,调用serviceDoneExecutingLocked把炸弹拆除,再调用requestServiceBindingsLocked 去执行r.app.thread.scheduleBindService 执行服务端的onBind函数拿到了返回的Binder再调用AMS的publishService把服务发布到AMS(在服务端的进程创建binder_proc(server) 在AMS的refs_by_node 和refs_by_desc 挂上server),AMS的onTransact

中读取到服务端返回的server(Binder)包装成BpBinder,然后调用c.conn.connected(从refs_by_desc 和 refs_by_node 找到InnerConnection)调用connect 所以到了客户端进程会把server的BpBinder 挂在refs_by_desc和refs_by_node上边。再调用Servcie.onServiceConnected 之后拆除炸弹。

转载请注明原文地址:http://www.2345lzwz.cn/read-143385.html
上一篇下一篇
00

New Post(0)