6.1.1.    bindService

由于有前面分析startService的代码实现过程,则对于bindService的代码分析就不用那么具体介绍,在介绍流程的同一时候更关注一些细节上的部分。

首先,bindService也是通过 ContextWrapper.bindService,再到ContextImpl的bindService,然后是bindServiceCommon,须要注意的是,传入的ServiceConnection被转换成IServiceConnection类型,

private boolean bindServiceCommon(Intent service,
ServiceConnection conn, int flags,

UserHandle user) {

IServiceConnection
sd;

sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),

mMainThread.getHandler(), flags);

int res = ActivityManagerNative.getDefault().bindService(

mMainThread.getApplicationThread(), getActivityToken(),

service, service.resolveTypeIfNeeded(getContentResolver()),

sd, flags, user.getIdentifier());

}

接下去是进入AMS的bindService,再调用ActiveServices.java 的bindServiceLocked,它会把IServiceConnection实例存放到ConnectionRecord里面,并运行bringUpServiceLocked,

int bindServiceLocked(IApplicationThread caller, IBinder token,

Intent service, String resolvedType,

IServiceConnection connection, int flags, int userId) {

ConnectionRecord c = new ConnectionRecord(b, activity,

connection, flags, clientLabel, clientIntent);

IBinder binder = connection.asBinder();

if ((flags&Context.BIND_AUTO_CREATE) != 0) {

s.lastActivity = SystemClock.uptimeMillis();

if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null){

return 0;

}

}

if (s.app != null && b.intent.received) {

// Service is already running, so we can immediately

// publish the connection.

try {

c.conn.connected(s.name, b.intent.binder);

} catch (Exception e) {

Slog.w(TAG, "Failure sending service " + s.shortName

+ " to connection " + c.conn.asBinder()

+ " (in " + c.binding.client.processName + ")", e);

}

// If this is the first app connected back to this binding,

// and the service had previously asked to be told when

// rebound, then do so.

if (b.intent.apps.size() == 1 && b.intent.doRebind) {

requestServiceBindingLocked(s, b.intent, callerFg, true);

}

} else if (!b.intent.requested) {

requestServiceBindingLocked(s, b.intent, callerFg, false);

}

}

依据之前的分析ServiceLocked会调用realStartServiceLocked,而realStartServiceLocked则先调用scheduleCreateService,完毕service的创建和Oncreate()的运行,然后运行requestServiceBindingsLocked,这个是bind服务相关处理,最后是sendServiceArgsLocked,这个是Start服务的处理。

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);

requestServiceBindingsLocked(r, execInFg);

sendServiceArgsLocked(r, execInFg, true);

}

requestServiceBindingsLocked再调用ActivityThread的方法scheduleBindService,在ActivityThread.java 中,它发出一个BIND_SERVICE事件,被handleBindService处理,

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, 0, 0, 0);

}

这里先调用服务的onBind方法,由于服务是重载的,所以会运行详细服务类的方法,并返回服务里的binder实例,这个binder随后会被使用到,

当中AMS的publishService方法被调用,在 ActivityManagerService.java中又会调用   ActiveServices.java 的publishServiceLocked,

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {

for (int conni=r.connections.size()-1; conni>=0; conni--) {

ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);

for (int i=0; i<clist.size(); i++) {

ConnectionRecord c = clist.get(i);

try {

c.conn.connected(r.name, service);

} …

serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);

这里主要调用到c.conn.connected,c就是ConnectionRecord,其成员conn是一个IServiceConnection类型实例,这在前面有提到,connected则是事实上现类的方法。

对于IServiceConnection,它是一个接口,位置在(frameworks\base): core/java/android/app/IServiceConnection.aidl,aidl定义例如以下,它仅仅有一个接口方法connected,

oneway interface IServiceConnection {

void connected(in ComponentName name, IBinder service);

}

其服务端的实如今LoadedApk.java,例如以下,InnerConnection类是在ServiceDispatcher的内部类,并在ServiceDispatcher的构造函数里面实例化的,其方法connected也是调用的ServiceDispatcher的方法connected,

private static class InnerConnection extendsIServiceConnection.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);

}

}

}

ServiceDispatcher(ServiceConnection conn,

Context context, Handler activityThread, int flags) {

mIServiceConnection = new InnerConnection(this);

mConnection = conn;

mContext = context;

mActivityThread = activityThread;

mLocation = new ServiceConnectionLeaked(null);

mLocation.fillInStackTrace();

mFlags = flags;

}

这里就再回到我们前面的ContextImpl里面bindServiceCommon方法里面,这里进行ServiceConnection转化为IServiceConnection时,调用了mPackageInfo.getServiceDispatcher,mPackageInfo就是一个LoadedApk实例,

/*package*/ LoadedApk mPackageInfo;

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,

UserHandle user) {

IServiceConnection sd;

sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),

mMainThread.getHandler(), flags);

}

所以,getServiceDispatcher会创建一个ServiceDispatcher实例,并将ServiceDispatcher实例和ServiceConnection实例形成KV对,并在ServiceDispatcher的构造函数里将ServiceConnection实例c赋值给ServiceConnection的成员变量mConnection,

public 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);

}

这样,在运行ServiceDispatcher的connected方法时,就会调用到ServiceConnection的

onServiceConnected,完毕绑定ServiceConnection的触发。

public void doConnected(ComponentName name, IBinder service) {

if (old != null) {

mConnection.onServiceDisconnected(name);

}

// If there is a new service, it is now connected.

if (service != null) {

mConnection.onServiceConnected(name, service);

}

}

至此,就运行完了bindService的主要过程。

我们以下用一张图来总结这个流程,

android4.4组件分析--service组件-bindService源代码分析的更多相关文章

  1. Tomcat组件梳理—Service组件

    Tomcat组件梳理-Service组件 1.组件定义 Tomcat中只有一个Server,一个Server可以用多个Service,一个Service可以有多个Connector和一个Contain ...

  2. android4.4组件分析--service组件

    6       Service 6.1            service介绍 6.1.1.            基本介绍 Service是Android四大组件之中的一个(其余的是activit ...

  3. Android成长日记-Android四大组件之Service组件的学习

    1.什么是Service? Service是Android四大组件中与Activity最相似的组件,它们都代表可执行的程序,Service与Activity的区别在于:Service一直在后台运行,它 ...

  4. Android服务之bindService源代码分析

    上一篇分析startService时没有画出调用ActivityManagerService之前的时序图,这里画出bindService的时序图.它们的调用流程是一致的. 先看ContextWrapp ...

  5. Hadoop源代码分析

    http://wenku.baidu.com/link?url=R-QoZXhc918qoO0BX6eXI9_uPU75whF62vFFUBIR-7c5XAYUVxDRX5Rs6QZR9hrBnUdM ...

  6. Hadoop源代码分析(完整版)

    Hadoop源代码分析(一) 关键字: 分布式云计算 Google的核心竞争技术是它的计算平台.Google的大牛们用了下面5篇文章,介绍了它们的计算设施. GoogleCluster:http:// ...

  7. 转:RTMPDump源代码分析

    0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...

  8. RTMPdump(libRTMP) 源代码分析 5: 建立一个流媒体连接 (NetConnection部分)

    ===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...

  9. Fragment事务管理源代码分析

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/53132952 本文出自: [HansChen的博客] 概述 在Fragment使用中 ...

随机推荐

  1. HTTP真的很简单(转)

    原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! 前言 在看这篇文章的时候 ...

  2. Graphics.DrawString 方法

    MSDN上的解释: 在指定位置而且用指定的 Brush 和Font 对象绘制指定的文本字符串. public void DrawString( string s, Font font, Brush b ...

  3. STL源代码分析——STL算法remove删除算法

    前言 因为在前文的<STL算法剖析>中,源代码剖析许多.不方便学习,也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的remove删除算法. ...

  4. hdu 1420(Prepared for New Acmer)(中国剩余定理)(降幂法)

    Prepared for New Acmer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O ...

  5. 第1周 SQL Server 如何执行一个查询

    原文:第1周 SQL Server 如何执行一个查询 大家好,欢迎来到第1周的SQL Server性能调优培训.在我们进入SQL Server性能调优里枯燥难懂的细节内容之前,我想通过讲解SQL Se ...

  6. [Windows Phone] 地图控制项的经纬度

    原文:[Windows Phone] 地图控制项的经纬度 前言 本文主要示范如何使用地图经纬度以及显示地标和行人街道,并透过卷轴控制地图缩放比例的功能. ? 实作 step1 建立专案. ? step ...

  7. 排列组合相关算法 python

    获取指定长度得全部序列 通过事件来表述这个序列,即n重伯努利实验(二项分布)的全部可能结果.比如时间a表示为: a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 假设每次实验为从 ...

  8. Android KitKat 4.4 Wifi移植AP模式和网络共享的调试日志

    Tethering技术在移动平台上已经运用的越来越广泛了.它能够把移动设备当做一个接入点,其它的设备能够通过Wi-Fi.USB或是Bluetooth等方式连接到此移动设备.在Android中能够将Wi ...

  9. 【转】QT样式表 (QStyleSheet)

    作者:刘旭晖 Raymond 转载请注明出处Email:colorant@163.comBLOG:http://blog.csdn.net/colorant/ 除了子类化Style类,使用QT样式表( ...

  10. 在汉澳sinox2014建立ZFS高可靠文件存储系统

    在汉澳sinox2014建立ZFS高可靠文件存储系统 汉澳sinox2014能够用比較小的固态硬盘安装,文件系统能够用zfs系统存放. 请准备一些硬盘,比方三块SCSI硬盘:da0,da1,da2 如 ...