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://xiahunao.cn/news/1620916.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【翻译】开发人员的技术写作

HTML、CSS、JavaScript、Python、PHP、C、Dart--有这么多的编程语言&#xff0c;你甚至可能完全精通其中的几种但是&#xff0c;当我们的目标是写出更多、更好的代码时&#xff0c;我们用日常语言写作和交流的方式变得越来越重要......甚至可能被忽略了。 我们写代码和围绕代码…

AIGC用于智能写作的技术综述-达观数据

导语 图1. ChatGPT生成的关于智能写作的介绍 智能写作指使用自然语言处理技术来自动生成文本内容。这种技术通过分析给定语料库&#xff0c;学习文本的结构和语法&#xff0c;然后利用这些信息来生成新的文本。智能写作可以用来快速生成高质量的文本内容&#xff0c;并且可…

玩转ChatGPT:论文辅助写作(附Claude测评)

一、写在前面 嘿&#xff01;嘿&#xff01;嘿&#xff01;大家好&#xff0c;今天我们来聊一下使用GPT们进行论文辅助写作。不过&#xff0c;我要先交代一下&#xff0c;GPT的使用门槛比较高&#xff0c;不少童鞋都用不上。所以&#xff0c;我极力推荐一个平替产品——Claude…

帮你的英文写作一键纠错,微软升级版AI批改软件有这些亮点

你的英语还好吗&#xff1f; 学英语时&#xff0c;“听说读写”是四大核心要素&#xff0c; 而“写”可谓是英语学习中最考验学习者综合语言运用能力的一项。 在写作的时候&#xff0c;你会面临写错、单词匮乏以及语法错误等诸多问题&#xff0c;但如果让你自己或者找别人修改…

系统集成项目管理工程师【中级】考证学习资料知识点整理分享——第二章《信息系统集成及服务管理》,持续更新中........

系统集成项目管理工程师(中级)考证学习资料整理分享,持续更新中........ 目 录 第二章《信息系统集成及服务管理》 一、信息系统集成及服务管理 (一)信息系统集成及服务管理的内容 (二)信息系统集成及服务管理的推进 1.实施信息系统集成及服务资质管理制度 1)…

webassembly003 ggml GGML Tensor Library part-3

关于pthread_create()和pthread_join() #include <stdio.h> #include <pthread.h>void *thread_func(void *arg) {int *num (int *)arg;printf("Hello from thread! arg%d\n", *num);pthread_exit(NULL); }int main() {pthread_t thread;int arg 10;i…

数据结构--树4.2(二叉树)

目录 一、二叉树的定义和特点 1、定义 2、特点 二、二叉树的基本形态 1、空二叉树 2、只有一个根结点 3、根结点只有左子树 4、根结点只有右子树 5、根结点既有左子树又有右子树 6、斜树 7、满二叉树 8、满二叉树和完全二叉树 三、二叉树的性质 一、二叉树的定义和…

Presto之Driver个数

一. 前言 在Presto的Stage Performace中&#xff0c;每个Operator中都会有Driver个数的显示&#xff0c;如下图所示。本文主要介绍Presto中是如何决定Driver的个数的。 二. Driver个数 在Presto中&#xff0c;一个pipeline中启动多少个Driver&#xff0c;是由此Pipeline处理的S…

新增收货地址【项目 商城】

新增收货地址【项目 商城】 新增收货地址1 新增收货地址-数据表创建2 新增收货地址-创建实体类3 新增收货地址-持久层3.1 各功能的开发顺序3.2 规划需要执行的SQL语句3.3 接口与抽象方法3.4 配置SQL映射 测试4 新增收货地址-业务层4.1 规划异常4.2 接口与抽象方法 测试5 新增收…

epoll() 多路复用 和 两种工作模式

1.epoll API 介绍 typedef union epoll_data {void *ptr;int fd;uint32_t u32;uint64_t u64; } epoll_data_t;struct epoll_event {uint32_t events; /* Epoll events */epoll_data_t data; /* User data variable */ };常见的Epoll检测事件&#xff1a;- EPOLLIN- EPOLLOUT- …

农村农产品信息展示网站的设计与实现(论文+源码)_kaic

摘 要 随着软件技术的迅速发展,农产品信息展示的平台越来越多,传统的农产品显示方法将被计算机图形技术取代。这种网站技术主要把农产品的描述、农产品价格、农产品图片等内容&#xff0c;通过计算机网络的开发技术&#xff0c;在互联网上进行展示&#xff0c;然后通过计算机网…

如何识别计算机病毒,怎样识别计算机病毒

电脑病毒不仅影响电脑的正常使用&#xff0c;有时候还会威胁到我们的个人信息包括财务信息的安全。下面就让学习啦小编教大家怎样识别计算机病毒吧。 识别计算机病毒的方法 病毒一般通过自我隐藏的方式来达到自己的目的&#xff0c;那么病毒一般都隐藏在系统的什么地方呢?一般…

计算机病毒为了隐藏,识别计算机病毒的方法

识别计算机病毒的方法 病毒为了能随系统启动而自启动对电脑进行危害操作&#xff0c;通常会把自己设置为自动启动。更有甚者&#xff0c;它们还会将自己注册成系统服务&#xff0c;优先于其他程序启动。下面是小编收集整理的识别计算机病毒的方法&#xff0c;欢迎阅读。 识别计…

可以查杀计算机病毒的软件,怎样彻底查杀计算机病毒

电脑中毒后很可能后导致电脑出现无法开机,卡死等各种的情况&#xff0c;那么怎样彻底查杀计算机病毒呢?学习啦小编分享了彻底查杀计算机病毒的方法&#xff0c;希望对大家有所帮助。 彻底查杀计算机病毒方法一 打开腾讯电脑管家&#xff0c;并找到杀毒页面 选择【闪电查杀】等…

检查和清除计算机病毒可以使用,如何深入检查和杀死计算机病毒

当我们的计算机感染病毒时&#xff01;如果我们想深入查杀&#xff0c;该怎么办&#xff1f;以下是学习编辑器深入检查和杀死计算机病毒的方法的详细介绍&#xff01;希望对您有帮助&#xff01; 一种深度检测计算机病毒的方法: 垃圾清除软件建议安装金山卫士&#xff0c;它可以…

2. 两数相加(中等系列)

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

如何根据公司名称来筛选快递

在查询快递物流的时候&#xff0c;如果想要对快递公司名称一致的单号进行筛选&#xff0c;该怎么办呢&#xff1f;不知道如何操作的宝贝们&#xff0c;下面请随小编一起来试试。 需要哪些工具&#xff1f; 快递批量查询高手 快递单号若干 怎么快速查询&#xff1f; 首先&…

关于名字

为什么80%的码农都做不了架构师&#xff1f;>>> 书不尽言&#xff0c;言不尽意。言者所以在意&#xff0c;得意而忘言。先从程序里的变量名说起。作为程序员&#xff0c;我们知道&#xff0c;大部分时候&#xff0c;我们要求程序中的变量名是唯一的。比如数据库里的…

2023-2029全球与中国电子级丙二醇甲醚醋酸酯市场现状及未来发展趋

电子级丙二醇甲醚醋酸酯的定义 丙二醇甲醚醋酸酯(PMA)&#xff0c;也称丙二醇单甲醚乙酸酯&#xff0c;是一种无色、有特殊气味的高级溶剂。PMA分子中既有醚键&#xff0c;又有羰基&#xff0c;羰基又形成了酯的结构&#xff0c;同时又有烷基&#xff1b;PMA同一分子中极性与非…

2022-2028年中国低温固化粉末涂料行业市场发展调研及未来前景规划报告

报告类型:产业研究 报告格式:电子版、纸介版、电子+纸介 出品单位:智研咨询-产业信息网 智研咨询发布的《2022-2028年中国低温固化粉末涂料行业市场发展调研及未来前景规划报告》共十四章。首先介绍了低温固化粉末涂料行业市场发展环境、低温固化粉末涂料整体运行态势等,…