bindService的调用流程

news2024/12/24 20:37:47

使用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.coloradmin.cn/o/937995.html

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

相关文章

剑指 Offer 19. 正则表达式匹配(C++实现)

剑指 Offer 19. 正则表达式匹配https://leetcode.cn/problems/zheng-ze-biao-da-shi-pi-pei-lcof/ 动态规划&#xff1a;通过dp数组剪枝 只需要对各种情况进行分类处理即可 vector<vector<int>> dp;bool helper(const string& s, const int i, const string&am…

R语言常用数学函数

目录 1. - * / ^ 2.%/%和%% 3.ceiling,floor,round 4.signif,trunc,zapsamll 5.max,min,mean,pmax,pmin 6.range和sum 7.prod 8.cumsum,cumprod,cummax,cummin 9.sort 10. approx 11.approx fun 12.diff 13.sign 14.var和sd 15.median 16.IQR 17.ave 18.five…

YOLOv5、YOLOv8改进:NAMAttention注意力机制

目录 1.简介 2.YOLOv5代码修改 2.1增加以下NAMAttention.yaml文件 2.2common.py配置 2.3yolo.py配置 1.简介 paper:https://arxiv.org/pdf/2111.12419.pdf code:https://github.com/Christian-lyc/NAM 摘要 注意机制是近年来人们普遍关注的研究兴趣之一。它帮助…

day 28 地图

from pyecharts.charts import Map from pyecharts.options import VisualMapOpts# 创建一个地图对象 map Map() # 准备数据 data [("北京市", 99),("上海市", 199),("湖南省", 399),("广东省", 499) ] # 添加数据 map map.add(&qu…

Redis数据结构全解析【万字详解】

文章目录 前言一、SDS1、SDS的必要性2、SDS的数据结构3、SDS的优势O&#xff08;1&#xff09;复杂度获取字符串长度二进制安全不会发生缓冲区溢出节省空间 二、链表1、结构设计2、优缺点 三、压缩列表1、结构设计2、连续更新3、压缩列表的缺陷 四、哈希表1、结构设计2、哈希冲…

Python小知识 - 八大排序算法

八大排序算法 排序算法是计算机科学中非常重要的一个研究领域。排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在计算机内部&#xff0c;而外部排序是数据记录在计算机外部&#xff0c;这里我们主要讨论内部排序。 内部排序中的算法大致可以归纳为四类&…

Matlab图像处理-乘法运算

乘法运算 两幅图像进行乘法运算主要实现两个功能&#xff1a; 一是可以实现掩模操作&#xff0c;即屏蔽图像的某些部分&#xff1b; 二是如果一幅图像乘以一个常数因子&#xff0c;如果常数因子大于1&#xff0c;将增强图像的亮度&#xff0c;如果因子小于1则会使图像变暗。…

day 28 折线图

from pyecharts.charts import Line from pyecharts.options import TitleOpts, LabelOpts# 分别打开三哥国家文件 import jsonf_us open("D:/美国.txt", "r", encoding"UTF-8") f_jp open("D:/日本.txt", "r", encoding&…

OpenCV基础知识(9)— 视频处理(读取并显示摄像头视频、播放视频文件、保存视频文件等)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。OpenCV不仅能够处理图像&#xff0c;还能够处理视频。视频是由大量的图像构成的&#xff0c;这些图像是以固定的时间间隔从视频中获取的。这样&#xff0c;就能够使用图像处理的方法对这些图像进行处理&#xff0c;进而达到…

无涯教程-Python机器学习 - Unsupervised Learning函数

无监督学习 顾名思义,它与监督式机器学习方法或算法相反,这意味着在无监督的机器学习算法中,我们没有任何监督者可以提供任何类型的指导。在没有监督学习算法那样的自由的情况下,无监督学习算法非常方便,因为在这种情况下我们没有预先标签训练数据,而我们想从输入数据中提取有…

学信息系统项目管理师第4版系列03_文件与标准

审核未通过&#xff0c;删除文件部分&#xff0c;仅保留标准化相关内容&#xff0c;重发 12. 标准化 12.1. 采用国际标准和国外先进标准的程度分为等同采用、修改采用和等效采用 3 种 12.1.1. 【高21上选20】 12.1.2. 采用指与国际标准在技术内容和文本结构上相同,或者与国…

图的邻接矩阵与邻接表

目录 一、图的概念 二、邻接矩阵 2.1 邻接矩阵存储 2.2 邻接矩阵结构 2.3 构造邻接矩阵 2.4 边的添加 三、邻接表 3.1 邻接矩阵存储 3.2 邻接表结构 3.3 构造邻接表 3.4 边的添加 三、 图的遍历 一、图的相关概念 图是由顶点集合及顶点间的关系组成的一种数据结构&…

微服务dubbo

微服务是一种软件开发架构风格&#xff0c;它将一个应用程序拆分成一组小型、独立的服务&#xff0c;每个服务都可以独立部署、管理和扩展。每个服务都可以通过轻量级的通信机制&#xff08;通常是 HTTP/REST 或消息队列&#xff09;相互通信。微服务架构追求高内聚、低耦合&am…

Mybatis学习|第一个Mybatis程序

1.创建一个数据库以及一个用户表&#xff0c;并插入三条数据用来测试 2.创建一个空的maven项目 在pom.xml中导入本次测试用到的三个依赖&#xff0c;mysql驱动、mybatis依赖、以及单元测试junit依赖 将这个 空的maven项目当成一个父项目&#xff0c;再创建一个空的maven子项目用…

并发编程基础知识篇--进程和线程的区别

目录 进程和线程 进程 线程 进程与线程的区别总结 扩展小知识 程序计数器为什么是私有的? 虚拟机栈和本地方法栈为什么是私有的? 简单了解堆和方法区 多进程和多线程区别 Java中的多线程 进程和线程 进程 在一个操作系统中&#xff0c;每个独立执行的程序都可称之…

Linux操作系统--shell编程(运算符)

语法: "$((运算式))" 或 "$[运算式]" 下面我们介绍几种Linux操作系统中的运算符的使用方式: 方式1:这一个使用比较麻烦,不推荐使用 方式2:推荐使用

软考A计划-系统集成项目管理工程师-小抄手册(共25章节)-中

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

BUUCTF [SWPU2019]Web1

​ 这是一道sql二次注入题目&#xff0c;但是注入点并不在登录处 注册一个用户然后登录 广告申请处进行sql注入 你会发现过滤了很多关键字 空格#information等等 这里用到了一些绕过技巧 使用 /**/ 代替空格 union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1…

【软件测试】Web自动化测试框架有哪些以及操作流程

测试行业现在70%是以手工测试为主&#xff0c;那么只有20%是自动化测试&#xff0c;剩下的10%是性能测试。 有人可能会说&#xff0c;我现在做手工&#xff0c;我为什么要学自动化呢&#xff1f;我去学性能更好性能的人更少&#xff1f; 其实&#xff0c;性能的要求比自动化要…

D - President - 背包dp

分析&#xff1a; 需要让所有x大于y的对应的z的总数大于z总共的数量的一半&#xff0c;找最小需要转化的数量&#xff0c;那么可以转化为01背包问题&#xff0c;z作为体积&#xff0c;每组的x和y都可以计算出一个值表示需不需要转化&#xff0c;作为背包价值&#xff0c;如果x大…