Service源码分析系列(二):bindService流程分析
来源:互联网 发布:鉴别声音的软件 编辑:程序博客网 时间:2024/06/14 04:42
Service源码分析系列(二):bindService流程分析
之前一篇分析了Service启动流程中的startService,这篇来分析Service的绑定,bindService。
Service源码分析系列(一):startService
Activity
本文从Activity的startService(Intent service)入手分析
- 先看看在Activity中怎么绑定一个Service(常规做法),代码如下
private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 绑定成功 ... } @Override public void onServiceDisconnected(ComponentName name) { // 绑定结束 ... } private void f(){ Intent intent = new Intent(this, XXXService.class); // bindService的具体实现在ContextImpl // BIND_AUTO_CREATE参数具体使用的代码 ActivityServices??? bindService(intent,conn,BIND_AUTO_CREATE); }
ContextImpl
- ContextImpl的bindService,bindService最终调用bindServiceCommon,代码如下
@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { // mMainThread.getHandler(),传入的handle是主线程的Handle! 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) { // 第一步,将传入的ServiceConnection转化为IServiceConnection返回,这不下面具体分析 // mPackgeInfo是LoadedApk sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } // 5.0以后禁止Service隐式绑定,判断和startService一样 validateServiceIntent(service); try { IBinder token = getActivityToken(); ... // 第二步,Binder调用AMS的bindService方法,下面具体分析 int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); return res != 0; } ... } }
LoadedApk
Local state maintained about a currently loaded .apk.
LoadedApk对象是APK文件在内存中的表示。 Apk文件的相关信息,诸如Apk文件的代码和资源,甚至代码里面的Activity,Service等组件的信息我们都可以通过此对象获取。
- 第一步调用LoadedApk的getServiceDispatcher,将ServiceConnection转化为能在进程间传递的Binder接口——IServiceConnection,因为Service的绑定很有可能是跨进程的。
- IServiceConnection的实现类是ServiceDispatcher.InnerConnection,ServiceDispatcher里面保存了当前的ServiceConnection和相应的InnerConnection。
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null; // private final ArrayMap<Context, // ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices // 根据当前的Context获取ArrayMap<ServiceConnection, // LoadedApk.ServiceDispatcher> ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); if (map != null) { // 如果存在,尝试根据当前的ServiceConnection获取ServiceDispatcher sd = map.get(c); } if (sd == null) { // 如果与ServiceConnection对应的ServiceDispatcher不存在,创建一个保存了当前ServiceConnection的ServiceDispatcher对象, // 并将之前传入的主线的Handle保存,同时创建一个InnerConnection对象保存 sd = new ServiceDispatcher(c, context, handler, flags); if (map == null) { map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); mServices.put(context, map); } // 将该ServiceConnection与ServiceDispatcher关系保存 map.put(c, sd); } else { // 如果最开始就获取到ServiceDispatcher,比如多次bindService, // 就会调用ServiceDispatcher的validate判断此次bindService是否合法 // validate的判断逻辑比较简单,1.判断当前的context是否和之前bindService的一样 2.判断当前handler是否是主线程的handle // 以上两个条件都满足的情况下正常执行,反之抛出相应的异常 sd.validate(context, handler); } return sd.getIServiceConnection(); } }
ActivityManagerService
public abstract class ActivityManagerNative extends Binder implements IActivityManager
public interface IActivityManager extends IInterface
从中可以看出ActivityManagerNative是一个Binder类,Activity的启动已经通过Binder调用转交到系统服务中了。
IActivityManager Binder具体实现是ActivityManagerService,最终调用到ActivityManagerService的bindService
调用进入ActivityManagerService的进程
- ActivityManagerService的bindService代码如下
public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException { ... synchronized(this) { // 调用ActiveServices的bindServiceLocked方法 return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
ActiveServices
ActiveServices是AMS中专门抽出来管理Service活动的类,包括启动、绑定等。
- ActiveServices的bindServiceLocked调用了bringUpServiceLocked
- bringUpServiceLocked调用了realStartServiceLocked
- realStartServiceLocked代码如下
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... try { ... // 第一步,调用ApplicationThread的scheduleCreateService方法,之后会实例化Service并调用Service的onCreate方法, // 不会调用onStartCommand,详见Service详解及源码分析系列(一):startService app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); } ... // 第二步,调用requestServiceBindingsLocked requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); // 第三步,注意下面的注释!!,分析待补充 // If the service is in the started state, and there are no // pending arguments, then fake up one so its onStartCommand() will // be called. if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null)); } // StartItem的taskRemoved如果是false的话,调用下面方法会调用Service的onStartCommand!!! sendServiceArgsLocked(r, execInFg, true); ... }
- 第一步,调用ApplicationThread的scheduleCreateService方法,之后会实例化Service并调用Service的onCreate方法,详见Service详解及源码分析系列(一):startService
- 第二步调用requestServiceBindingsLocked,之后调用到requestServiceBindingLocked,代码如下
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { ... if ((!i.requested || rebind) && i.apps.size() > 0) { try { ... // 调用ApplicationThread的scheduleBindService方法 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); } ... } ... return true; }
ApplicationThread
IApplicationThread thread;
public interface IApplicationThread extends IInterface
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread
ApplicationThreadNative的具体实现是ActivityThread中的ApplicationThread
ApplicationThread实现了许多Activity和Service 启动、暂停等有关的操作
调用进入应用程序的进程
- 调用ApplicationThread的scheduleBindService,scheduleBindService通过mH发送一个H.BIND_SERVICE消息,mH收到该消息调用 handleBindService(BindServiceData data),代码如下
private void handleBindService(BindServiceData data) { // 根据token获取Service token具体分析??? Service s = mServices.get(data.token); if (s != null) { try { try { // rebind具体分析??? if (!data.rebind) { // 调用Service的onBind,返回给客户端调用的Binder IBinder binder = s.onBind(data.intent);// 调用AMS的publishService,进而通知客户端连接成功??? ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder); } else { // onRebind??? s.onRebind(data.intent); // ??? ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } ensureJitEnabled(); } } ... } }
- Service源码分析系列(二):bindService流程分析
- Service启动流程源码分析之bindService(二)
- android4.4组件分析--service组件-bindService源码分析
- BindService 流程分析
- bindService 分析---之二
- vlc源码分析(二) 播放流程
- vlc源码分析(二) 播放流程
- Android中bindService的细节之二:从进程的角度分析绑定Service的流程【Service所在进程已存在】
- android WifiDisplay 源码分析系列 (二)
- DbUtils源码分析系列(二)
- 车道检测源码分析系列(二)
- Service启动流程源码分析之startService(一)
- Service启动流程源码分析(一):startService
- qemu源码分析系列(二)
- springmvc源码分析系列-请求处理流程
- Android中bindService的细节之一:从进程的角度分析绑定Service的流程【Service所在进程首次启动】
- linux3.5.4 ptrace源码分析二(系列二)
- Android服务之bindService源码分析
- 每天回顾linux命令(wc)
- 在Notepad++或Sublime中使用正则表达式替换
- OSGi规范与原理(3)--生命周期
- 用C语言写冒泡排序
- pip换源(豆瓣源)
- Service源码分析系列(二):bindService流程分析
- Leetcode 172 Factorial Trailing Zeroes
- linux 安装mysql
- PointT
- 深度探索C++ 对象模型【第一章1】
- Leetcode 290 Word Pattern
- 区块链有哪些技术特征
- OSGi规范与原理(杂)
- Spark-core 运行原理