博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bindService过程
阅读量:6069 次
发布时间:2019-06-20

本文共 11380 字,大约阅读时间需要 37 分钟。

       有了前面一篇《Service启动过程》,bindService应该很好分析了。但不用看代码也能估计出来,AMS需要缓存BinderProxy并转发给Client,跟Provider一样。
       如果是进程内,ActivityThread中直接返回的是ContentProviderNative对象,即进程内直接调用ContentProvider函数而不是RPC。如果是进程外,那么ActiviyThread会找AMS要ContentProviderHolder,最终得到的ContentProviderProxy。
       对于进程内和进程外,bindService的过程也会一样吗?我们估计,进程内得到的是一个Binder,而进程外得到的是一个BInderProxy。

1747    @Override1748    public boolean bindService(Intent service, ServiceConnection conn,1749            int flags) {1751        return bindServiceCommon(service, conn, flags, Process.myUserHandle());1752    }复制代码

1761    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,1762            UserHandle user) {1763        IServiceConnection sd;1767        if (mPackageInfo != null) {1768            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),1769                    mMainThread.getHandler(), flags);1770        } else {1772        }1774        try {1775            IBinder token = getActivityToken();1782            int res = ActivityManagerNative.getDefault().bindService(1783                mMainThread.getApplicationThread(), getActivityToken(),1784                service, service.resolveTypeIfNeeded(getContentResolver()),1785                sd, flags, user.getIdentifier());1790            return res != 0;1791        } catch (RemoteException e) {1792            return false;1793        }1794    }复制代码
关注一下参数有三个:第一个是Intent,第二个是连接监听,第三个是bindService的flags。
首先是构造了一个IServiceConnection,其次调用了AMS的startService。

957    public final IServiceConnection getServiceDispatcher(ServiceConnection c,958            Context context, Handler handler, int flags) {959        synchronized (mServices) {960            LoadedApk.ServiceDispatcher sd = null;961  ArrayMap
map=mServices.get(context)965 if (sd == null) {966 sd = new ServiceDispatcher(c, context, handler, flags);967 if (map == null) {968 map = new ArrayMap
();969 mServices.put(context, map);970 }971 map.put(c, sd);972 } 975 return sd.getIServiceConnection();976 }977 }复制代码
原来ServiceConnection就是一个纯粹的接口,要为其加一层皮用于跨进程通信,通信用的倒不是ServiceDispatcher而是其中的通信代表 . 。ServiceDispatcher画个uml图记忆一下,服务连接和断开消息的发布者。
mServices的key是Context这说明一个Context只能bindService一次(同时)。返回值是ServiceDispatcher的内部类InnerConnection extends IServiceConnection.Stub。
还有个释放ServiceConnection的函数也看看:

979    public final IServiceConnection forgetServiceDispatcher(Context context,980            ServiceConnection c) {981        synchronized (mServices) {982            ArrayMap
map983 = mServices.get(context);984 LoadedApk.ServiceDispatcher sd = null;985 if (map != null) {986 sd = map.get(c);987 if (sd != null) {988 map.remove(c);989 sd.doForget();990 if (map.size() == 0) {991 mServices.remove(context);992 }993 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {994 ArrayMap
holder995 = mUnboundServices.get(context);996 if (holder == null) {997 holder = new ArrayMap
();998 mUnboundServices.put(context, holder);999 }1002 ex.fillInStackTrace();1003 sd.setUnbindLocation(ex);1004 holder.put(c, sd);1005 }1006 return sd.getIServiceConnection();1007 }1008 }1009 ArrayMap
holder1010 = mUnboundServices.get(context);1011 if (holder != null) {1012 sd = holder.get(c);1013 if (sd != null) {1014 RuntimeException ex = sd.getUnbindLocation();1018 }1019 }1026 }1027 }复制代码
------------------------------------------------------------------------------------------------
开始要执行AMS.bindService了

14907    public int bindService(IApplicationThread caller, IBinder token,14908            Intent service, String resolvedType,14909            IServiceConnection connection, int flags, int userId) {1491614917        synchronized(this) {14918            return mServices.bindServiceLocked(caller, token, service, resolvedType,14919                    connection, flags, userId);14920        }14921    }复制代码

671    int bindServiceLocked(IApplicationThread caller, IBinder token,672            Intent service, String resolvedType,673            IServiceConnection connection, int flags, int userId) {677        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);685        ActivityRecord activity = null;686        if (token != null) {687            activity = ActivityRecord.isInStackLocked(token);688            if (activity == null) {690                return 0;691            }692        }720721        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;722723        ServiceLookupResult res =724            retrieveServiceLocked(service, resolvedType,725                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);732        ServiceRecord s = res.record;733734        final long origId = Binder.clearCallingIdentity();735736        try {754            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);755            ConnectionRecord c = new ConnectionRecord(b, activity,756                    connection, flags, clientLabel, clientIntent);757758            IBinder binder = connection.asBinder();759            ArrayList
clist = s.connections.get(binder);760 if (clist == null) {761 clist = new ArrayList
();762 s.connections.put(binder, clist);763 }779 clist = mServiceConnections.get(binder);780 if (clist == null) {781 clist = new ArrayList
();782 mServiceConnections.put(binder, clist);783 }784 clist.add(c);785786 if ((flags&Context.BIND_AUTO_CREATE) != 0) {787 s.lastActivity = SystemClock.uptimeMillis();788 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {789 return 0;790 }791 }807 // 这里开始不会走的,因为IBinder还没有发布,即没有缓存到AMS中808 if (s.app != null && b.intent.received) {811 try {812 c.conn.connected(s.name, b.intent.binder);813 } catch (Exception e) {817 }818822 if (b.intent.apps.size() == 1 && b.intent.doRebind) {823 requestServiceBindingLocked(s, b.intent, callerFg, true);824 }825 } else if (!b.intent.requested) {826 requestServiceBindingLocked(s, b.intent, callerFg, false);827 }828829 getServiceMap(s.userId).ensureNotStartingBackground(s);830831 } finally {833 }834835 return 1;836 }复制代码
取得IBinder放到了b.intent.binder中,即放到了AppBindRecord中,而AppBinderRecord绑定了Intent信息,且存放到了ServiceRecord.bindings中。从c.conn.connected来看最终调用了 .connected,这个是在Client应用层代码中的,所以基本可以断定bringUpServiceLocked这一步坑定准备好了AppBindRecord. .binder
------------------------------------------------------------------------------------------------
看看如何取到IBinder的

1430    private final void realStartServiceLocked(ServiceRecord r,1431            ProcessRecord app, boolean execInFg) throws RemoteException {14401446        boolean created = false;1447        try {1448            String nameTerm;1449            int lastPeriod = r.shortName.lastIndexOf('.');1460            app.thread.scheduleCreateService(r, r.serviceInfo,1461                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),1462                    app.repProcState);1463            r.postNotification();1464            created = true;1465        } catch (DeadObjectException e) {1467            mAm.appDiedLocked(app);1468        } finally {1469            if (!created) {1470                app.services.remove(r);1471                r.app = null;1472                scheduleServiceRestartLocked(r, false);1473                return;1474            }1475        }1477        requestServiceBindingsLocked(r, execInFg);1489        sendServiceArgsLocked(r, execInFg, true);1505    }复制代码

1121    private final boolean requestServiceBindingLocked(ServiceRecord r,1122            IntentBindRecord i, boolean execInFg, boolean rebind) {1127        if ((!i.requested || rebind) && i.apps.size() > 0) {1128            try {1130                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);1131                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,1132                        r.app.repProcState);1138            } catch (RemoteException e) {1140                return false;1141            }1142        }1143        return true;1144    }复制代码

2748    private void handleBindService(BindServiceData data) {2749        Service s = mServices.get(data.token);2752        if (s != null) {2753            try {2756                try {2757                    if (!data.rebind) {2758                        IBinder binder = s.onBind(data.intent);2759                        ActivityManagerNative.getDefault().publishService(2760                                data.token, data.intent, binder);2761                    } else {2762                        s.onRebind(data.intent);2765                    }2767                } catch (RemoteException ex) {2768                }2769            } catch (Exception e) {2775            }2776        }2777    }复制代码

14929    public void publishService(IBinder token, Intent intent, IBinder service) {1493414935        synchronized(this) {14939            mServices.publishServiceLocked((ServiceRecord)token, intent, service);14940        }14941    }复制代码

838    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {839        final long origId = Binder.clearCallingIdentity();840        try {843            if (r != null) {844                Intent.FilterComparison filter845                        = new Intent.FilterComparison(intent);846                IntentBindRecord b = r.bindings.get(filter);847                if (b != null && !b.received) {848                    b.binder = service;849                    b.requested = true;849                     // 这里下次不需要再找Client要IBinder了850                    b.received = true;851                    for (int conni=r.connections.size()-1; conni>=0; conni--) {852                        ArrayList
clist = r.connections.valueAt(conni);853 for (int i=0; i
------------------------------------------------------------------------------------------------
从代码来看,不管怎样bindService都会穿越到AMS中,AMS中记录了BindProxy。当在进程内bindService时,AMS将BindProxy传递到进程内部,会转化为Binder,最终就进程内直接调用了;如果是进程外bindService,那么从AMS中拿到的还是BinderProxy,依然是RPC。IBinder在创建进程中变为Binder,在其他进程变为BinderProxy,这得去读一下Binder机制源码,如果要彻底理解需要看看Binder驱动代码。

转载地址:http://difgx.baihongyu.com/

你可能感兴趣的文章
鬼谷子
查看>>
我的友情链接
查看>>
Microsoft Visual SourceSafe OLE Automation
查看>>
android源码是不是包含联想的支持?
查看>>
iostat 命令监控磁盘IO
查看>>
java反射详解
查看>>
android无法识别adb devices解决方法
查看>>
站长常用服务器软件总结
查看>>
CSS纯图片圆角Box的实现技巧
查看>>
Maven:简介(1)
查看>>
安卓SDK 安装问题
查看>>
Kubernetes 1.8.4 手动安装教程-安装Etcd(二)
查看>>
解析各大电子商务网站订单号的生成方式
查看>>
IOS开发-Foundation笔记
查看>>
[转]Mybatis Plus 插件注册机
查看>>
UTF8 与 UTF8 +BOM 区别
查看>>
Mac系统升级到10.9(mavericks)时安装php扩展问题解决
查看>>
搬家!
查看>>
CSS技巧收集——巧用滤镜
查看>>
IDEA Tomcat 内存溢出
查看>>