bindService的调用流程

使用bindService去调用service,如果有多个客户端调用,onBind方法只会被调用一次,由于bindService嗲处理中,AMS是一个中间商,猜测这个处理也是AMS里进行的,这里我们再看看bindService的调用流程

 

public class ContextWrapper extends Context {

    Context mBase;

    public ContextWrapper(Context base) {

        mBase = base;

    }

    public boolean bindService(Intent service, ServiceConnection conn,

            int flags) {

        return mBase.bindService(service, conn, flags);

    }

ContextImpl.java

    // bindService

    @Override

    public boolean bindService(Intent service, ServiceConnection conn, int flags) {

        warnIfCallingFromSystemProcess();

        return bindServiceCommon(service, conn, flags, Process.myUserHandle());

    }

    // bindServiceCommon

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, UserHandle user) {

        IServiceConnection sd;

        ...

//包装ServiceConnection

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

                mMainThread.getHandler(), flags);

        ...

        int res = ActivityManagerNative.getDefault().bindService(

                mMainThread.getApplicationThread(), getActivityToken(), service,

                service.resolveTypeIfNeeded(getContentResolver()),

                sd, flags, getOpPackageName(), user.getIdentifier());

        ...

    }

这里是通过binder和AMS进行通信,一次binder调用

ActivityManagerNative.java

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {

        protected IActivityManager create() {

            IBinder b = ServiceManager.getService("activity");

            if (false) {

                Log.v("ActivityManager", "default service binder = " + b);

            }

            IActivityManager am = asInterface(b);

            if (false) {

                Log.v("ActivityManager", "default service = " + am);

            }

            return am;

        }

    };

}

    static public IActivityManager asInterface(IBinder obj) {

        if (obj == null) {

            return null;

        }

        IActivityManager in =

            (IActivityManager)obj.queryLocalInterface(descriptor);

        if (in != null) {

            return in;

        }

        return new ActivityManagerProxy(obj);

    }

public abstract class Singleton<T> {

    private T mInstance;

    protected abstract T create();

    public final T get() {

        synchronized (this) {

            if (mInstance == null) {

                mInstance = create();

            }

            return mInstance;

        }

    }

}

即包装ServiceManager.getService("activity");

继续查看bindServiceCommon方法

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

            handler, UserHandle user) {

        IServiceConnection sd;

        if (conn == null) {

            throw new IllegalArgumentException("connection is null");

        }

        if (mPackageInfo != null) {

            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);

        } else {

            throw new RuntimeException("Not supported in system context");

        }

        validateServiceIntent(service);

        try {

            IBinder token = getActivityToken();

            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null

                    && mPackageInfo.getApplicationInfo().targetSdkVersion

                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

                flags |= BIND_WAIVE_PRIORITY;

            }

            service.prepareToLeaveProcess(this);

            int res = ActivityManagerNative.getDefault().bindService(

                mMainThread.getApplicationThread(), getActivityToken(), service,

                service.resolveTypeIfNeeded(getContentResolver()),

                sd, flags, getOpPackageName(), user.getIdentifier());

这个sd是怎么来的呢

ServiceDispatcher用来包装ServiceConnection

创建binder实体对象,用来响应回调

LoadedApk.java

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

            } else {

                sd.validate(context, handler);

            }

            return sd.getIServiceConnection();

        }

    }

        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;

        }

InnerConnection用来进行binder通信

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

                }

            }

        }

 

 

AMS端作为Proxy进行调用connected方法

IServiceConnection.Stub的定义

vi out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/app/IServiceConnection.java

/*

 * This file is auto-generated.  DO NOT MODIFY.

 * Original file: frameworks/base/core/java/android/app/IServiceConnection.aidl

 */

package android.app;

/** @hide */

public interface IServiceConnection extends android.os.IInterface

{

/** Local-side IPC implementation stub class. */

public static abstract class Stub extends android.os.Binder implements android.app.IServiceConnection

{

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

{

switch (code)

{

case INTERFACE_TRANSACTION:

{

reply.writeString(DESCRIPTOR);

return true;

}

case TRANSACTION_connected:

{

data.enforceInterface(DESCRIPTOR);

android.content.ComponentName _arg0;

if ((0!=data.readInt())) {

_arg0 = android.content.ComponentName.CREATOR.createFromParcel(data);

}

else {

_arg0 = null;

}

android.os.IBinder _arg1;

_arg1 = data.readStrongBinder();

this.connected(_arg0, _arg1);

return true;

}

}

return super.onTransact(code, data, reply, flags);

}

private static class Proxy implements android.app.IServiceConnection

{

private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote)

AMS通过调用传入的proxy来和client端进行交互

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.java

    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 {

//binder调用,AMS调用client的方法,把service的binder传过去

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

                            } catch (Exception e) {

                                Slog.w(TAG, "Failure sending service " + r.name +

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

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

                            }

                        }

                    }

               ...

    }

ConnectionRecord.java

final class ConnectionRecord {

    final AppBindRecord binding;    // The application/service binding.

    final ActivityRecord activity;  // If non-null, the owning activity.

    final IServiceConnection conn;  // The client connection.

AMS中

    public 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 descriptors

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

        }

    }

在ActivityManagerService.java中有定义

    final ActiveServices mServices;

ActiveServices.java中

bindServiceLocked

bringUpServiceLocked

public final class ActiveServices {

    private final void realStartServiceLocked(ServiceRecord r,

            ProcessRecord app, boolean execInFg) throws RemoteException {

      ...

        r.app = app;

       ...

            app.thread.scheduleCreateService(r, r.serviceInfo,

                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),

                    app.repProcState);

            r.postNotification();

     ...

     //

        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

     ...

    }

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,

            boolean execInFg, boolean rebind) throws TransactionTooLargeException {

        if (r.app == null || r.app.thread == null) {

            // If service is not currently running, can't yet bind.

            return false;

        }

        if ((!i.requested || rebind) && i.apps.size() > 0) {

            try {

                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;

            } catch (TransactionTooLargeException e) {

… …

            }

        }

        return true;

    }

final class ProcessRecord {

    IApplicationThread thread;

这里是binder调用

在启动应用的过程中,通过对AMS的binder调用,传给了AMS一个ApplicationThread的proxy对象。

public abstract class ApplicationThreadNative extends Binder

        implements IApplicationThread {

    /**

ActivityThread.java中有内部类

    private class ApplicationThread extends ApplicationThreadNative {

        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

调用到ApplicationThread的

        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;

            sendMessage(H.BIND_SERVICE, s);

        }

处理该消息时调用ActivityThread的

    private void handleBindService(BindServiceData data) {

        Service s = mServices.get(data.token);

        if (s != null) {

            try {

                data.intent.setExtrasClassLoader(s.getClassLoader());

                data.intent.prepareToEnterProcess();

                try {

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

                    }

                    ensureJitEnabled();

                } catch (RemoteException ex) {

                    throw ex.rethrowFromSystemServer();

                }

            } catch (Exception e) {

            }

        }

    }

在server进程中,通过调用AMS服务publishService把binder对象传给AMS

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/56183.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

百亿补贴通用H5导航栏方案 | 京东云技术团队

背景 在移动端页面中&#xff0c;由于屏幕空间有限&#xff0c;导航条扮演着非常重要的角色&#xff0c;提供了快速导航到不同页面或功能的方式。用户也通常会在导航条中寻找他们感兴趣的内容&#xff0c;因此导航条的曝光率较高。在这样的背景下&#xff0c;提供一个动态灵活…

爬虫(bilibili热门课程记录)

什么是爬虫&#xff1f;程序蜘蛛&#xff0c;沿着互联网获取相关信息&#xff0c;收集目标信息。 一、python环境安装 1、先从Download Python | Python.org中下载最新版本的python解释器 2、再从Download PyCharm: Python IDE for Professional Developers by JetBrains中下…

SpringCloud/SpringBoot多模块项目中配置公共AOP模块实现打印子模块Controller所有请求参数与日志

项目中遇到多个模块需要打印Controller请求日志&#xff0c;在每个模块里面加AOP并且配置单独的切面笔者认为代码冗余&#xff0c;于是乎就打算把AOP日志打印抽离成一个公共模块&#xff0c;谁想用就引入Maven坐标就行。 定义公共AOP模块 并编写AOP工具 AOP模块pom.xml如下 &…

Docker 轻量级可视化工具Portainer

1. 是什么 Portainer 是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 2. 安装 2.1 官网 https://www.protainer.io/ https://docs.portainer.io/ce-2.9/start/install/server/docker/linux 2.2 …

Java“牵手”天猫商品sku信息API接口数据,天猫API接口申请指南

天猫平台商品sku属性信息接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取天猫商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品销量接口API是一种用于获取电商平台上商品sku属性数据的接口&#…

【Docker】网络

文章目录 Docker 网络基础Docker网络管理Docker网络架构CNMLibnetwork驱动 常见的网络类型 Docker 网络管理命令docker network createdocker network inspectdocker network connectdocker network disconnectdocker network prunedocker network rmdocker network ls docker …

抖音短视频SEO矩阵系统源码开发及开发者思路分享......

抖音矩阵号/抖音短视频SEO矩阵系统源码开发及开发者思路分享: 短视频获客系统支持短视频智能剪辑、短视频定时发布&#xff0c;短视频排名查询及优化&#xff0c;智能客服等&#xff0c;那么短视频seo系统开发时需要开发哪些功能呢&#xff1f;今天我就跟大家分享一下我们的开发…

Java“牵手”天猫商品历史价格信息API接口数据,天猫API接口申请指南

天猫平台商品历史价格接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取天猫商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片、最低价、当前价格、价格信息等详细信息 。 获取商品历史价格接口API是一种用于获取电商平台…

Visual Studio 2022 右键单击项目没有出现View | View Class Diagram(Visual Studio 无法使用类设计器)

文章目录 问题描述原因.NET Core项目.NET Framework项目 其他VS2022相关文章 问题描述 当我们在Solution Explorer窗口右键单击项目时&#xff0c;快捷菜单中没有出现“查看”&#xff0c;或者出现了“查看”&#xff0c;但是“查看”里没有View Class Diagram。 原因 首先…

算法通关村第十一关——搞清位运算

源码、反码和补码 很多人都记不清源码、反码和补码的区分&#xff0c;都是二进制&#xff0c;其实记忆起来很简单&#xff0c;分为正数和负数来记。正数的原码、反码和补码都是一样的&#xff0c;负数的原码符号位为1&#xff0c;反码是在原码的基础上进行改变&#xff1a;保持…

【Linux的成长史】Linux的发展史

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集 数据库专栏 初阶数据结构 &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如…

AIGC之GPT-4:GPT-4的简介(核心原理/意义/亮点/技术点/缺点/使用建议)、使用方法、案例应用(计算能力/代码能力/看图能力等)之详细攻略

AIGC之GPT-4&#xff1a;GPT-4的简介(核心原理/意义/亮点/技术点/缺点/使用建议)、使用方法、案例应用(计算能力/代码能力/看图能力等)之详细攻略 解读&#xff1a;在2022年11月横空出世的ChatGPT&#xff0c;打遍天下无敌手的时候&#xff0c;就知道会有这么一天&#xff0c;知…

深度学习12:胶囊神经网络

目录 研究动机 CNN的缺陷 逆图形法 胶囊网络优点 胶囊网络缺点 研究内容 胶囊是什么 囊间动态路由算法 整体框架 编码器 损失函数 解码器 传统CNN存在着缺陷&#xff08;下面会详细说明&#xff09;&#xff0c;如何解决CNN的不足&#xff0c;Hinton提出了一种对于图…

spark中排查Premature EOF: no length prefix available

报错信息 /07/22 10:20:28 WARN DFSClient: Error Recovery for block BP-888461729-172.16.34.148-1397820377004:blk_15089246483_16183344527 in pipeline 172.16.34.64:50010, 172.16.34.223:50010: bad datanode 172.16.34.64:50010 [DataStreamer for file /bdp/data/u9…

Linux —— nfs文件系统

简介 NFS 是Network File System的缩写&#xff0c;即网络文件系统。一种使用于分散式文件系统的协定&#xff0c;由Sun公司开发&#xff0c;于1984年向外公布。功能是通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据&#xff0c;让应用程序在客户端通过网络访问位…

apex和pl/sql学习记录2

验证后过程函数代码插眼儿 -- 登录后验证过程3 create or replace PROCEDURE TEST_USER_WXX3_PRO ASV_USER_ID NUMBER(20);V_ROLE_ID NUMBER(20);V_PERM_ID NUMBER(20);V_DEPT_ID NUMBER(20);V_USER_NAME NVARCHAR2(64);V_JOB_NUMBER NVARCHAR2(32);V_M…

Hbuild 打包H5项目

1、输入用户信息登录Hbuilder编辑器&#xff1b; 2、进入manifest.json配置文件&#xff1b;获取AppID信息&#xff1b;&#xff08;可以点击DCloud AppID使用说明进行查看详情&#xff09; 3、进入DCloud开发者中心https://dev.dcloud.net.cn/&#xff1b;登录用户和密码&…

Linux目录结构与文件管理 (02)(四)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、查看文件内容 二、创建文件 三、删除文件 四、 移动文件 五、复制文件 六、编辑文件内容 总结 前言 今天是在昨天的基础上继续学习&#xff0c;主要…

【VLDB 2023】基于预测的云资源弹性伸缩框架MagicScaler,实现“高QoS,低成本”双丰收

开篇 近日&#xff0c;由阿里云计算平台大数据基础工程技术团队主导&#xff0c;与计算平台MaxCompute团队、华东师范大学数据科学与工程学院、达摩院合作&#xff0c;基于预测的云计算平台资源弹性伸缩框架论文《MagicScaler: Uncertainty-aware, Predictive Autoscaling 》被…

Flutter实现动画列表AnimateListView

由于业务需要&#xff0c;在打开列表时&#xff0c;列表项需要一个从右边飞入的动画效果&#xff0c;故封装一个专门可以执行动画的列表组件&#xff0c;可以自定义自己的动画&#xff0c;内置有水平滑动&#xff0c;缩放等简单动画。花里胡哨的动画效果由你自己来定制吧。 功…