12.源码阅读(IPC Binder机制-android api 26)

简介: 调用bindService方法绑定服务最终会执行Service的onBind方法并在ServiceConnection的onServiceConnected中得到IBinder对象,我们从源码角度看看这一过程是如何进行的首先从ContextImpl的...

调用bindService方法绑定服务最终会执行Service的onBind方法并在ServiceConnection的onServiceConnected中得到IBinder对象,我们从源码角度看看这一过程是如何进行的

首先从ContextImpl的bindService看起

@Override
1538    public boolean bindService(Intent service, ServiceConnection conn,
1539            int flags) {
1540        warnIfCallingFromSystemProcess();
1541        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
1542                Process.myUserHandle());
1543    }
 private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
1582            handler, UserHandle user) {
1583        //注意这里得到的一个IServiceConnection在后边会用到
1584        IServiceConnection sd;
1585        ......
1588        if (mPackageInfo != null) {
1589            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
1590        } 
            ......
1602            int res = ActivityManager.getService().bindService(
1603                mMainThread.getApplicationThread(), getActivityToken(), service,
1604                service.resolveTypeIfNeeded(getContentResolver()),
1605                sd, flags, getOpPackageName(), user.getIdentifier());
1606        ......
1614    }
1615

ActivityManager.getService()这行代码我们已经非常熟悉了,前边看activity启动的时候就遇到过

4199    public static IActivityManager getService() {
4200        return IActivityManagerSingleton.get();
4201    }
        private static final Singleton<IActivityManager> IActivityManagerSingleton =
4204            new Singleton<IActivityManager>() {
4205                @Override
4206                protected IActivityManager create() {
4207                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
4208                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
4209                    return am;
4210                }
4211            };

ActivityManager.getService()得到的是IActivityManger,而IActivityManger是一个接口,所以我们要去看它的实现类ActivityManagerService中的bindService方法

ActivityManagerService中

public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        ......

        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

ActiveServices中

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
            ......
                                    try {
                                    //注意,这个方法和下边是殊途同归的
                                        bringUpServiceLocked(serviceRecord,
                                                serviceIntent.getFlags(),
                                                callerFg, false, false);
                                    } catch (RemoteException e) {
                                        /* ignore - local call */
                                    }
            ......
          
            if (s.app != null && b.intent.received) {

                ......

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

        ......
    }

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        ......
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
           ......
    }

需要找到 r.app.thread.scheduleBindService这个方法究竟是哪个类中的方法,r是ServiceRecord,那么到它里边去找发现app是ProcessRecord类,然后进入到ProcessRecord中去找thread,可以看到IApplicationThread thread,IApplicationThread很明显是一个接口,我们还要找到它的实现类才行,这里也不再卖关子了,我们要找的实现类就是ApplicationThread,而ApplicationThread是ActivityThread的一个内部类,所以去ActivityThread中继续寻找

public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            updateProcessState(processState, false);
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            sendMessage(H.BIND_SERVICE, s);
        }

private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

可以看到是通过handler发送了一个消息,找到这个消息的处理

case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
private void handleBindService(BindServiceData data) {
        //从集合中取出service,可以猜测服务在之前已经被存储起来了
        Service s = mServices.get(data.token);
       
        ......
                    if (!data.rebind) {
                        //调用service的onBind方法,这里终于找到了
                        IBinder binder = s.onBind(data.intent);
                        //这里是回调到onServiceConnected方法的关键
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                   ......
        }
    }

再次回到ActivityManagerService中

public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors
        if (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类中

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
                    + " " + intent + ": " + service);
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    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);
                            if (!filter.equals(c.binding.intent.intent)) {
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Not publishing to: " + c);
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Published intent: " + intent);
                                continue;
                            }
                            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
                            try {
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                                Slog.w(TAG, "Failure sending service " + r.name +
                                      " to connection " + c.conn.asBinder() +
                                      " (in " + c.binding.client.processName + ")", e);
                            }
                        }
                    }
                }

                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

关键代码

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

c表示ConnectionRecord,conn就是IServiceConnection,看到这个IServiceConnection我们很容易把它和ServiceConnection联系起来,是不是这样呢,其实这时候我们可以回到最初的那个地方埋下的伏笔,我们写了一句注释

//注意这里得到的一个IServiceConnection在后边会用到
IServiceConnection sd;

从代码ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);中就可以看出,每一个ConnectionRecord都是提前存入集合中保存的,那么每个ConnectionRecord中的IServiceConnection也就在那时候已经存在了,IServiceConnection是一个接口,我们同样要找到它的实现类,那么回到ContextImpl中,看看,这个IServiceConnection是如何创建出来的

        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
           sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        @Override
1564    public IServiceConnection getServiceDispatcher(ServiceConnection conn, Handler handler,
1565            int flags) {
1566        return mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
1567    }

进入LoadedApk中

public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1397            Context context, Handler handler, int flags) {
1398        synchronized (mServices) {
1399            LoadedApk.ServiceDispatcher sd = null;
1400            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
1401            if (map != null) {
1402                if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
1403                sd = map.get(c);
1404            }
1405            if (sd == null) {
1406                sd = new ServiceDispatcher(c, context, handler, flags);
1407                if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
1408                if (map == null) {
1409                    map = new ArrayMap<>();
1410                    mServices.put(context, map);
1411                }
1412                map.put(c, sd);
1413            } else {
1414                sd.validate(context, handler);
1415            }
1416            return sd.getIServiceConnection();
1417        }
1418    }
1419
                IServiceConnection getIServiceConnection() {
1553            return mIServiceConnection;
1554        }

看到这个
private final ServiceDispatcher.InnerConnection mIServiceConnection;

我们找到了IServiceConnection的实现类,InnerConnection,那么c.conn.connected(r.name, service, false);执行的就是它的connect方法

private static class InnerConnection extends IServiceConnection.Stub {
1489            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1490
1491            InnerConnection(LoadedApk.ServiceDispatcher sd) {
1492                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1493            }
1494
1495            public void connected(ComponentName name, IBinder service, boolean dead)
1496                    throws RemoteException {
1497                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1498                if (sd != null) {
1499                    sd.connected(name, service, dead);
1500                }
1501            }
1502        }
public void connected(ComponentName name, IBinder service, boolean dead) {
1569            if (mActivityThread != null) {
1570                mActivityThread.post(new RunConnection(name, service, 0, dead));
1571            } else {
1572                doConnected(name, service, dead);
1573            }
1574        }



public void connected(ComponentName name, IBinder service, boolean dead) {
1569            if (mActivityThread != null) {
1570                mActivityThread.post(new RunConnection(name, service, 0, dead));
1571            } else {
1572                doConnected(name, service, dead);
1573            }
1574        }

终于找到了,看下边

public void doConnected(ComponentName name, IBinder service, boolean dead) {
1585            ServiceDispatcher.ConnectionInfo old;
1586            ServiceDispatcher.ConnectionInfo info;
1587
1588            ......
1625            // If there was an old service, it is now disconnected.
1626            if (old != null) {
1627                mConnection.onServiceDisconnected(name);
1628            }
1629            ......
1632            // If there is a new service, it is now connected.
1633            if (service != null) {
                        //onServiceConnected被调用
1634                mConnection.onServiceConnected(name, service);
1635            }
1636        }

相关文章
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
368 2
|
7月前
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
478 2
|
8月前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
Ubuntu 开发工具 Android开发
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
本文介绍了在基于Ubuntu 22.04的环境下配置Python 3.9、安装repo工具、下载和同步AOSP源码包以及处理repo同步错误的详细步骤。
1280 0
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
604 1
|
开发工具 uml git
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
本文分享了下载AOSP源码的方法,包括如何使用repo工具和处理常见的repo sync错误,以及配置Python环境以确保顺利同步特定版本的AOSP代码。
2521 0
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
1216 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
|
Android开发
我的Android 进阶修炼(1): AOSP源码根目录结构
本文介绍了AOSP源码的根目录结构,提供了基于MTK9269 Android 9.0源码的目录说明,帮助读者了解AOSP源码的组织方式和各目录的功能。
1043 0
我的Android 进阶修炼(1): AOSP源码根目录结构
|
开发工具 Android开发 git
全志H713 Android 11 :给AOSP源码,新增一个Product
本文介绍了在全志H713 Android 11平台上新增名为myboard的产品的步骤,包括创建新的device目录、编辑配置文件、新增内核配置、记录差异列表以及编译kernel和Android系统的详细过程。
1161 0
|
Ubuntu 开发工具 Android开发
Repo下载、编译AOSP源码:基于Ubuntu 21.04,android-12.1.0_r27
文章记录了作者在Ubuntu 21.04服务器上配置环境、下载并编译基于Android 12.1.0_r27版本的AOSP源码的过程,包括解决编译过程中遇到的问题和错误处理方法。
1168 0

热门文章

最新文章