2:37 pm
Tuesday, 14 June 2022 (HKT)
Time in Hong Kong


概述

本文基于Android 10分析总结bindService流程,展示关键流程和关键类。

流程

整体流程分为App侧和SystemServer侧两大块。bindServicestartService一样,如果service对应的进程还未启动,那么会先启动对应的进程,然后在启动后再查找等待bind的调用。bindService()回调ActivityThread后,会publishService()发布服务,AMS收到服务发布时会查找等待bind的调用并完成绑定。即服务的启动和绑定是分离的。

Service生命周期

App

bindService类图

bindService_App流程

App提供ServiceConnection用于监听服务绑定情况,调用ContextImpl时,会从LoadedApk.getServiceDispatcher()获取包装了ServiceConnection和服务绑定相关逻辑的ServiceDispatcherServiceDispatcher通过Binder调用bindIsolatedService()发送到AMS进行下一步调用。

其中getServiceDispatcher()的实现比较简单。在LoadedApk.mServices :Map<Context, Map<ServiceConnection, ServiceDispatcher>>查找已有的ServiceDispatcher,没有的话直接创建新的返回并存入LoadedApk.mServices

应用层调用bindService()传入的ServiceConnectionLoadedApk.mService :Map<Context, Map<ServiceConnection, ServiceDispatcher>>以及该Map内的ServiceDispatcher保存了。

向AMS发出Binder调用时,使用的是ServiceDispatcher.InnerConnection这个对ServiceDispatcher的包装类。

ServiceDispatcher.InnerConnection被通过Binder传出,从Binder服务端即AMS侧对它的处理为IServiceConnection,该接口仅有一个方法connected()

SystemServer

AMS_bindService类图

整体流程

ActiveServices负责完成服务启动、Service的onBindonRebind(回调到ActivityThread根据rebind参数触发)、Client的ServiceConnection.onServiceConnected()ServiceConnection.onServiceDisconnected()的回调。其中,服务未启动时,首先启动服务,然后提前返回。在服务启动后由ActivityManagerService检查等待的bind请求,此时再执行bind流程。服务已启动的情况下,如果该client已经调用过bindService绑定该服务了,则回调client的ServiceConnection.onServiceConnected(),而不再回调Service的onBind()。如果client是首次绑定该Service,那么通过requestServiceBindingLocked()完成绑定和回调。

AMS_bindService整体流程

Client此前已经对该Service调用过bind了

这种情况下,不会再回调Service.onBind(),而是直接通过IServiceConnection.connected()返回IBinder给Client,回调Client的ServiceConnection.onServiceConnected()

这种情况下可能调用Rebind,流程与《Client此前没有bind该Service》接近。

Client此前没有bind该Service

调用requestServiceBindingLocked()将Client与Service绑定。回调到ActivityThread在App主线程完成Service.onBind()后,通过publishService()再回调到ActiveService,找到待绑定的ConnectionRecord,回调它保存的IServiceConnection.connected(),将Service的IBinder传递回到client,完成绑定。其中,IServiceConnection.connected()还有一点流程执行,最终回调到binderSerice使用的ServiceConnection.onServiceConnected()

Service_bind流程

服务所在的进程没有启动,先启动进程

startService()流程一致。如果进程没有启动,则会先启动进程。

App侧的回调流程:IServiceConnection.connected()到ServiceConnection.onServiceConnected()

Client发起AMS.bindIsolatedService()时传递的其实并不是应用层bindService()使用的ServiceConnection,而是经过层层包装后的InnerConnectionServiceDispatcher,以及真正和AMS的Binder通信接口IServiceConnection。当Service.onBind()完成后,回调到ActiveService,它调用IServiceConnection.connected()回调到Client。

App侧onServiceConnected处理流程