ServiceManager管理着系统中的所有服务,服务在启动的时候会注册到ServiceManager,其他进程要使用相应服务时需要先去ServiceManager中寻找,然后使用。

ServiceManager本身运行在一个单独的进程service_manager

api 23版本的源码分析:

bindService(intent, connection, Context.BIND_AUTO_CREATE);ContextWrapper#bindService()ContextImpl#bindService()ContextImpl#bindServiceCommon()ActivityManagerNative.getDefault().bindServiceActivityManagerNative.getDefault() 返回的是一个Proxy对象,因此就相当于 Proxy.bindServiceIActivityManager(继承IInterface接口), IActivityManager就相当于我们自定义的 IMyAidl 接口ActivityManagerNative 就是 Stub类,只是命名为具体的名字ActivityManagerNativeActivityManagerProxy 就是 Proxy类,是 ActivityManagerNative 的内部类

ActivityManagerNative#ActivityManagerProxy#bindService:

    public int bindService(IApplicationThread caller, IBinder token,Intent service, String resolvedType, IServiceConnection connection,int flags,  String callingPackage, int userId) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(caller != null ? caller.asBinder() : null);data.writeStrongBinder(token);service.writeToParcel(data, 0);data.writeString(resolvedType);data.writeStrongBinder(connection.asBinder());data.writeInt(flags);data.writeString(callingPackage);data.writeInt(userId);mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);reply.readException();int res = reply.readInt();data.recycle();reply.recycle();return res;}

里面会调用mRemote.transact方法,然后经过Binder驱动后到达服务端的ActivityManagerNative对象的onTransact方法:

//ActivityManagerNative.java@Overridepublic boolean onTransact(int code, Parcel data, Parcel reply, int flags)throws RemoteException {switch (code) {...case BIND_SERVICE_TRANSACTION: {data.enforceInterface(IActivityManager.descriptor);IBinder b = data.readStrongBinder();IApplicationThread app = ApplicationThreadNative.asInterface(b);IBinder token = data.readStrongBinder();Intent service = Intent.CREATOR.createFromParcel(data);String resolvedType = data.readString();b = data.readStrongBinder();int fl = data.readInt();String callingPackage = data.readString();int userId = data.readInt();IServiceConnection conn = IServiceConnection.Stub.asInterface(b);int res = bindService(app, token, service, resolvedType, conn, fl,callingPackage, userId);reply.writeNoException();reply.writeInt(res);return true;}...}

会调用bindService(app, token, service, resolvedType, conn, fl, callingPackage, userId);

这个bindService方法就是ActivityManagerService中的bindService方法,因为ActivityManagerService是继承ActivityManagerNative的:

public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {}

ActivityManagerService#bindService:

//ActivityManagerService.javapublic int bindService(IApplicationThread caller, IBinder token, Intent service,String resolvedType, IServiceConnection connection, int flags, String callingPackage,int userId) throws TransactionTooLargeException {enforceNotIsolatedCaller("bindService");// Refuse possible leaked file descriptorsif (service != null && service.hasFileDescriptors() == true) {throw new IllegalArgumentException("File descriptors passed in Intent");}if (callingPackage == null) {throw new IllegalArgumentException("callingPackage cannot be null");}synchronized(this) {return mServices.bindServiceLocked(caller, token, service,resolvedType, connection, flags, callingPackage, userId);}}

会调用ActiveServices的bindServiceLocked()方法,
ActiveServices#bindServiceLocked()这个方法分两种情况:
情况1. ActiveServices#bringUpServiceLocked()
情况2. ActiveServices#requestServiceBindingLocked(s, b.intent, callerFg, true);

为什么分为两种情况,涉及到 A进程访问B进程时的几种状态:

  1. 进程B没有启动,即整个B进程都没有启动

  2. 进程B启动了,但是里面的Service没创建出来

  3. 进程B启动了,里面的Service也创建了,但是Service没有被绑定过,回调onBind()

  4. 进程B启动了,里面的Service也创建了,但是Service已经被绑定过,回调onRebind()

1,2对应代码中的情况1;
3,4对应代码中的情况2。

ActiveServices#bindServiceLocked()的两种情况:

情况1,ActiveServices#bringUpServiceLocked()

1.1 APP已经创建

// APP 已经创建了,即进程已经启动了
if (app != null && app.thread != null) {
//则启动服务
realStartServiceLocked(r, app, execInFg);

private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {...app.thread.scheduleCreateService(r, r.serviceInfo,mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),app.repProcState);...}

参数app是一个 ProcessRecord 对象,每启动一个app就创建了一个进程,进程信息就保存在ProcessRecord里面。
app.thread就是ApplicationThread对象,ApplicationThread类定义在ActivityThread.java中,ApplicationThread对象保存在ActivityThread.java中。

/*** This manages the execution of the main thread in an* application process, scheduling and executing activities,* broadcasts, and other operations on it as the activity* manager requests.** {@hide}*/
public final class ActivityThread {...final ApplicationThread mAppThread = new ApplicationThread();...public static void main(String[] args) {...//创建ActivityThread对象ActivityThread thread = new ActivityThread();thread.attach(false);...}}

ActivityThread对象在ActivityThread的main方法里创建,也就是只要App启动了,必定会创建ActivityThread对象,也就必定会创建其成员属性ApplicationThread对象。

app.thread.scheduleCreateService(),会调用Handler发送一个CREATE_SERVICE消息,然后执行handleCreateService()方法:

public void handleMessage(Message msg) {...case CREATE_SERVICE:handleCreateService((CreateServiceData)msg.obj);...}
//ActivityThread.java//创建服务的方法
private void handleCreateService(CreateServiceData data) {...   java.lang.ClassLoader cl = packageInfo.getClassLoader();service = (Service) cl.loadClass(data.info.name).newInstance();//这里通过类加载器和反射加载的类在上述例子中就是Myservice...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);//mServices是一个ArrayMap,final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();...}

为什么要将service put到mServices中,因为service只能创建一次,只能bind一次,下次再调用bindService进行绑定服务时,先从mServices中寻找,如果找到了则判断service是否绑定了,如果还没有绑定,则调onBind进行绑定,如果已经绑定了,则调用onRebind。这个过程zhandleBindService()中:

private void handleBindService(BindServiceData data) {...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);}...
}

1.2 APP没有创建

回到ActiveServices#bringUpServiceLocked()方法中看第2种情况:

    private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,boolean whileRestarting) throws TransactionTooLargeException {...//APP没有创建,即B进程还没有启动,则启动B进程// Not running -- get it started, and enqueue this service record// to be executed when the app comes up.if (app == null) {if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,"service", r.name, false, isolated, false)) == null) {String msg = "Unable to launch app "+ r.appInfo.packageName + "/"+ r.appInfo.uid + " for service "+ r.intent.getIntent() + ": process is bad";Slog.w(TAG, msg);bringDownServiceLocked(r);return msg;}...
}

mAm是一个ActivityManagerService对象 final ActivityManagerService mAm;
ActivityManagerService#startProcessLocked:

private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {...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启动B进程,B进程启动后会启动Service。

情况2,ActiveServices#requestServiceBindingLocked(s, b.intent, callerFg, true)

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,boolean execInFg, boolean rebind) throws TransactionTooLargeException {...r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,r.app.repProcState);...
}

如果还没有绑定过(即Service的onBind方法还没有调用过),那么参数rebind为false;
如果已经绑定过(即Service的onBind方法已经调用过),那么参数rebind为true;

scheduleBindService方法会调用Handler发送一个BIND_SERVICE消息,然后调用handleBindService方法:

//ActivityThread.java//处理服务的绑定过程,根据Service是否已经绑定调用Service#onBind还是Service#onRebind
private void handleBindService(BindServiceData data) {...if (!data.rebind) {//不是rebind,即Service还没有绑定过,则调用onBindIBinder binder = s.onBind(data.intent);//获得了iBinder对象ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);} else {//是rebind,即Service已经绑定过,则调用onRebinds.onRebind(data.intent);ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);}...
}

2.1 rebind为false,则调用onBind

private void handleBindService(BindServiceData data) {...if (!data.rebind) {//不是rebind,即Service还没有绑定过,则调用onBindIBinder binder = s.onBind(data.intent);//获得了iBinder对象ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);}...
}

先调用了onBind获得了iBinder对象,这个iBinder对象在上述例子中就是MyService中创建的Stub对象。
然后调用 ActivityManagerNative.getDefault().publishService()
即调用ActivityManagerProxy.publishService(),通过Binder驱动最终调用ActivityManagerService.publishService()方法(这个过程和bindService过程一模一样,参看上面的bindService分析过程,这里就不分析了)。

ActivityManagerService.publishService():

    public void publishService(IBinder token, Intent intent, IBinder service) {// Refuse possible leaked file descriptorsif (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);}}

ActiveServices#publishServiceLocked:

//ActiveServices.javavoid publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {...//最终会调用客户端进程绑定服务时传入的ServiceConnection的onServiceConnected()回调方法c.conn.connected(r.name, service);...
}

ConnectionRecord c
IServiceConnection conn;

final class ConnectionRecord {final AppBindRecord binding;    // The application/service binding.final ActivityRecord activity;  // If non-null, the owning activity.//conn是客户端进程的IServiceConnection对象在AMS进程的代理对象final IServiceConnection conn;  // The client connection....
}

即conn是一个IServiceConnection对象,IServiceConnection是一个aidl接口,也就是说conn.connected方法调用过程也是一个Binder机制跨进程调用的过程。
AMS进程的 conn.connected 是如何调用到app进程的connection.onServiceConnected()方法的?
先看下app进程的ServiceConnection对象是如何转为IServiceConnection对象的,app调用bindService方法进行绑定服务时会在ContextImpl的bindServiceCommon()方法中对参数conn对象进行封装,转换为IServiceConnection对象sd,

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,UserHandle user) {IServiceConnection sd;if (conn == null) {throw new IllegalArgumentException("connection is null");}if (mPackageInfo != null) {sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),mMainThread.getHandler(), flags);...}

mPackageInfo时是LoadedApk对象,
LoadedApk#getServiceDispatcher方法:

//LoadedApk.javapublic 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();}}static final class ServiceDispatcher {private final ServiceDispatcher.InnerConnection mIServiceConnection;...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) throws RemoteException {LoadedApk.ServiceDispatcher sd = mDispatcher.get();if (sd != null) {sd.connected(name, service);}}}...IServiceConnection getIServiceConnection() {return mIServiceConnection;}...}

也就是说客户端进程的bindService方法会把传递进去的ServiceConnection conn参数转为InnerConnection对象sd,InnerConnection实现了IServiceConnection接口,并且是Stub类,而AMS进程的conn对象也实现了IServiceConnection接口,是个Proxy类。
也就是AMS进程调用 conn.connected 方法最终调用到app进程的connection.onServiceConnected()方法的过程是一个Binder机制跨进程调用的过程,这个过程中AMS进程是客户端(IServiceConnection.Stub.Proxy),app进程是服务端(IServiceConnection.Stub)。

2.2 rebind为true,则调用onRebind

回到handleBindService()方法看onRebind过程:

private void handleBindService(BindServiceData data) {...else {//是rebind,即Service已经绑定过,则调用onRebinds.onRebind(data.intent);ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);}...
}

总结

调用bindService()执行的流程:

ServiceManager是系统服务,运行在系统进程(service_manager进程)
ActivityManagerService是系统服务,运行在系统进程(system_server进程)

api 28版本的上述源码分析:

ContextWrapper#bindService():

    @Overridepublic boolean bindService(Intent service, int flags, Executor executor,ServiceConnection conn) {return mBase.bindService(service, flags, executor, conn);}

mBase是一个ContextImpl对象,
ContextImpl#bindService():

    @Overridepublic boolean bindService(Intent service, int flags, Executor executor, ServiceConnection conn) {warnIfCallingFromSystemProcess();return bindServiceCommon(service, conn, flags, null, null, executor, getUser());}

ContextImpl#bindServiceCommon

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,String instanceName, Handler handler, Executor executor, UserHandle user) {...int res = ActivityManager.getService().bindService(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, getOpPackageName(), user.getIdentifier());...}

分析下ActivityManager.getService().bindService:

//android/app/ActivityManager.javaprivate static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};/*** @hide*/public static IActivityManager getService() {return IActivityManagerSingleton.get();}

是不是看到了熟悉的IActivityManager.Stub.asInterface(b);也就是getService()返回的是IActivityManager.Stub.Proxy对象,即ActivityManager.getService().bindService最终调用的是IActivityManager.Stub.Proxy.bindService

bindService()流程源码分析相关推荐

  1. 【源码分析】storm拓扑运行全流程源码分析

    [源码分析]storm拓扑运行全流程源码分析 @(STORM)[storm] 源码分析storm拓扑运行全流程源码分析 一拓扑提交流程 一stormpy 1storm jar 2def jar 3ex ...

  2. Activity启动流程源码分析-浅析生命周期函数

    源码分析 接着上一篇 Activity启动流程源码分析-setContentView源码阅读 的讲解,本节介绍一下Activity的生命周期函数何时被调用 要看Activity的生命周期函数何时被调用 ...

  3. nimble源码学习——广播流程源码分析1

    广播流程源码分析1 在controller层有多种状态:广播.空闲.连接等等,这次分析的是广播这个状态或者叫 做角色.在前面controller层循环的分析中,可以明确controller层也有eve ...

  4. YOLOv3反向传播原理 之 全流程源码分析

    YOLOv3反向传播原理 之 全流程源码分析 1.YOLOv3网络训练中反向传播主体流程 1.1 初始化 1.2 batch内梯度累加 1.3 network和layer 中的关键变量 2.YOLO层 ...

  5. SpringBoot2 | SpringBoot启动流程源码分析(一)

    首页 博客 专栏·视频 下载 论坛 问答 代码 直播 能力认证 高校 会员中心 收藏 动态 消息 创作中心 SpringBoot2 | SpringBoot启动流程源码分析(一) 置顶 张书康 201 ...

  6. OkHttp原理流程源码分析

    OkHttp已经是非常流行的android客户端的网络请求框架,我其实在项目中使用也已经好几年了,之前一直把重心放在如何快速的搞定业务上.迭代的效率上,这一点来讲,对于一个公司优秀员工是没有毛病的.但 ...

  7. Activity启动流程源码分析(基于Android N)

    Activity启动流程源码分析 一个Activity启动分为两种启动方式,一种是从Launcher界面上的图标点击启动,另一种是从一个Activity中设置按钮点击启动另外一个Activity.这里 ...

  8. 二次开发:flowable审批流程实践与创建流程源码分析

    二次开发:flowable审批流程实践与创建流程源码分析 上一篇已经描述了基于开源项目https://doc.iocoder.cn/的flowable的快速开发,创建了一个租户,创建了用户和相应的岗位 ...

  9. springboot MVC视图解析流程源码分析

    Servlet的基础知识 为什么要先了解Servlet的知识呢,因为后面你会看到我们所熟悉的SpringMVC其实也是一个Servlet,只是它封装了很多的东西并和Spring进行了整合,后面我们进行 ...

最新文章

  1. java.lang.UnsatisfiedLinkError:no jhdf5 in java.library.path问题的解决
  2. redis php web管理,redis web管理工具phpRedisAdmin安装
  3. linux pytorch环境配置,linux下使用conda安装pytorch,并配置pytorch
  4. 联想gen系列服务器,Hpe Microserver Gen10 Plus开箱
  5. Springboot源码——应用程序上下文分析
  6. fota 差分包_chaoFOTA
  7. 复古风格海报设计欣赏|蒸汽波了解下
  8. 2021-2025年中国云计算数据中心IT资产处置(ITAD)行业市场供需与战略研究报告
  9. elasticsearch 更新数据 (部分字段更新)
  10. 【21天学习挑战赛】哪吒邀你参加Java研讨班
  11. 余弦窗cosine window
  12. log4j之additivity
  13. matlab的损失函数mse,MSELoss损失函数
  14. 不是青蛙就是王子,不是王子就是青蛙
  15. 全球及中国家庭自动化行业前景动态及投资趋势预测报告(新版)2022-2027
  16. js图片上传功能的实现 FileReader()
  17. 牛客网-直通BAT面试算法精品课购买优惠码
  18. html隐藏电话中间几位,ios 手机号码隐藏中间4位为*号
  19. 当B站“不再二次元”,破圈易,盈利难!
  20. lorawan的工作原理_详解LoRaWAN网络架构和协议内容

热门文章

  1. linux下qt打印功能如何实现,QT实现操控打印机打印图片
  2. MySQL性能优化(四):SQL优化
  3. vim 操作出现 Found a swap file by the name xxxx
  4. php time 转化,php时间戳转换
  5. Python是个什么鬼?为什么建筑设计都要学它?
  6. sql 查询_嵌套查询
  7. 中兴防火墙配置_中兴防火墙
  8. 30 分钟看懂 CatBoost(Python代码)
  9. 自动生成文件目录列表
  10. 师古创今匠心品质,打造红木中式整装