system_service进程里 调用SystemManager.getService("activity") 直接返回ams的引用?
我们知道ActivityManager是运行在system_service进程里的,但是最近看代码发现在这个进程的其他服务线程里为了获取AMS调用:
ActivityManagerService am = (ActivityManagerService)ServiceManager.getService("activity");
验证了下,返回的am确实是AMS的实例,没问题
我们一般用ServiceManager.getService在其他进程中获取AMS服务,返回的一个是远端binder代理,
如果用在同一进程中会怎样? 为了解释这个问题,首先要复习下binder通信知识
Binder IPC模型

Binder在内核中两种形式: Binder实体(binder_node), Binder引用(binder_ref)
binder_node:
{
binder_proc* proc; //service进程信息
void__user* ptr; //service实例指针
}
binder_ref:
{
binder_proc* proc; //service进程信息
binder_node* node; //指向Binder实体
unit32_t desc; //service handle值,唯一标识一个service
}
两个典型流程
1. service在ServiceManager注册:
在内核创建一个binder实体(橙色矩形),一个binder引用(蓝色六边形),
在ServiceManager里用map保存这个service的名字和binder引用(蓝色曲线四边形)。
2. Client通过ServiceManager getService("activity"):
Client首先与ServiceManager进程通信
Client端先构造一个handle为0的binder引用(灰色曲线四边形),
通过这个引用向内核发送数据(包含servcie的名字"activity"),
在内核空间创建一个ServiceManager的biner引用(灰色六边形),
找到ServiceManager的binder实体(灰色矩形),
然后唤醒ServiceManager进程,
通过binder实体中的ServiceManager实例,调用它的getService方法,
ServiceManager通过名字"activity"找到ActivityManagerService服务的binder引用,把数据写回内核
在内核为Client进程创建一个ActivityManagerService binder引用(蓝色六边形)
返回包含binder的handle值的数据给Client,在Client创建一个app端的binder引用(蓝色曲线四边形)
然后Client可以通过这个app端的binder引用与AMS进行通信。
在app-service通信中,binder内核驱动担任dns的功能,也就是通过binder引用,找对应服务的binder实体
回到开始问题:
上面的步骤是在Client端请求AMS服务,这里Client与AMS在两个不同进程,
而如果在同一进程,AMS运行在system_server进程中,如果其他服务线程通过SystemManager.getService("activity")请求AMS服务,
那么这个接口将直接返回 ActivityManagerService实例的引用。
原因主要是在case 2步骤中蓝色部分,binder驱动会进行检查:
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
switch (fp->type) {
...
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
struct binder_ref *ref = binder_get_ref(proc, fp->handle,
fp->type == BINDER_TYPE_HANDLE); if (ref == NULL) {
binder_user_error("%d:%d got transaction with invalid handle, %d\n",
proc->pid,
thread->pid, fp->handle);
return_error = BR_FAILED_REPLY;
goto err_binder_get_ref_failed;
}
if (ref->node->proc == target_proc) {
if (fp->type == BINDER_TYPE_HANDLE)
fp->type = BINDER_TYPE_BINDER;
else
fp->type = BINDER_TYPE_WEAK_BINDER;
fp->binder = ref->node->ptr;
fp->cookie = ref->node->cookie;
binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
trace_binder_transaction_ref_to_node(t, ref);
binder_debug(BINDER_DEBUG_TRANSACTION,
" ref %d desc %d -> node %d u%016llx\n",
ref->debug_id, ref->desc, ref->node->debug_id,
(u64)ref->node->ptr);
} else {
struct binder_ref *new_ref; new_ref = binder_get_ref_for_node(target_proc, ref->node);
if (new_ref == NULL) {
return_error = BR_FAILED_REPLY;
goto err_binder_get_ref_for_node_failed;
}
fp->binder = ;
fp->handle = new_ref->desc;
fp->cookie = ;
binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
trace_binder_transaction_ref_to_ref(t, ref,
new_ref);
binder_debug(BINDER_DEBUG_TRANSACTION,
" ref %d desc %d -> ref %d desc %d (node %d)\n",
ref->debug_id, ref->desc, new_ref->debug_id,
new_ref->desc, ref->node->debug_id);
}
} break;
...
}
}
看红色代码
首先判断ref->node->proc == target_proc,即判断注册的AMS进程和要获取AMS的进程是否是同一个,
如果是,则改写fp->type为BINDER_TYPE_BINDER,设fp->binder = ref->node->ptr;
后续把AMS的binder实体中的实例引用返回给请求者,
所以通过SystemManager.getService("name")在同一进程获取服务,会直接返回这个服务实例的引用,这是binder驱动支持的。 当然在一个进程里有更直接的办法来获取,但是在某些特殊情况用这种办法也可以,只是效率稍低,因为经历了一次与serviceManager的ipc。
system_service进程里 调用SystemManager.getService("activity") 直接返回ams的引用?的更多相关文章
- startActivityForResult调用另外一个Activity获取返回结果
startActivityForResult(intent,requestCode)可以调用另外一个Activity,并返回结果. 换头像案例 activity_main.xml <?xml v ...
- Android中调用另一个Activity并返回结果-以模拟选择头像功能为例
场景 Android中点击按钮启动另一个Activity以及Activity之间传值: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/detail ...
- bug:进程可调用函数而子线程调用报错
在调试摄像头时遇到问题:在主进程里调用下述函数能够成功,但在子线程里创建时总是失败,错误打印为 sched: RT throttling activated. UniqueObj<OutputS ...
- 如何退出Activity?如何安全退出已调用多个Activity的Application?
如何退出Activity?如何安全退出已调用多个Activity的Application? 退出Activity直接调用finish()方法 //用户点击back键就是退出一个Activity 退出 ...
- 调用另一个Activity
<转>调用另一个Activity Intent对象的使用 范例说明 前一个范例介绍了如何运用切换Layout的方式,进行手机页面间的转换.如果要转换的页面并不单只是背景.颜色或文字内容的不 ...
- Wayland中的跨进程过程调用浅析
原文地址:http://blog.csdn.net/jinzhuojun/article/details/40264449 Wayland协议主要提供了Client端应用与Server端Composi ...
- 如何安全退出已调用多个Activity的Application?
如何退出Activity?如何安全退出已调用多个Activity的Application? 退出Activity直接调用finish()方法 //用户点击back键就是退出一个Activity 退出 ...
- QProcess 进程类—调用外部程序
http://blog.csdn.net/newbee520/article/details/8279101 启动一个新的进程的操作非常简单,只需要将待启动的程序名称和启动参数传递给start() ...
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法.可是我们能发现Messenger是以串行的方式来处理client ...
随机推荐
- parameter– tRPRE and tRPST
DDR读数据有效之前,有一段时间DQS(DQS#)需为低(高),此段时间即为read preamble,tRPRE. 同理,读数据结束之前,某段时间为read postamble,tRPST.
- 理解最短路径-Dijkstra算法
最短路径—Dijkstra算法和Floyd算法 透彻理解迪杰斯特拉算法 Dijkstra算法的使用条件:图中不存在负权边. ---------------------------有待验证------- ...
- Delphi 设计模式:《HeadFirst设计模式》Delphi2007代码---组合模式之Menus[转]
1 2{<HeadFirst设计模式>之组合模式 } 3{ 组合与单项的抽象父类 } 4{ 编译工具:Delphi2007 for win32} 5{ E-M ...
- java求1000以内的水仙花数
水仙花数是指一个 n 位数 ( n>=3 ),它的每个位上的数字的 n 次幂之和等于它本身.(例如:1^3 + 5^3 + 3^3 = 153) 三位的水仙花数共有4个,分别为:153.370. ...
- jmeter参数化之用户自定义变量
1. 用badboby进行录制,录制完成后保存,用JMeter格式进行保存,如:登陆.jmx 2. 在jmeter中打开保存的文件登陆.jmx. 3.线程组右击-添加-配置元件-用户定 ...
- Lamdba表达式的代码使用讲解
public class Lambda{ public static void main(String[] args) { repeat(10, (i)->System.out.print(&q ...
- Eclipse配置jstl标准标签库详解
安装JSTL1.2 日期:2017-06-27 下载jstl1.2版本,下载地址:http://repo2.maven.org/maven2/javax/servlet/jstl/ 用压缩包打开jst ...
- Luogu P1073 最优贸易(最短路)
P1073 最优贸易 题意 题目描述 \(C\)国有\(n\)个大城市和\(m\)条道路,每条道路连接这\(n\)个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这\(m\)条道路中有 ...
- 20190902+0903合集-NOIP模拟
一直没时间写QwQ 于是补一下. Day 1 晚饭吃的有点恶心…… $1s\,2s\,5s$ 还开 -O2 ?? 有点恐怖. T1 猛的一想: 把外面设成一个点, 向入口连一条权为排队时间的边 从出口 ...
- Ajax 用法简介
使用Ajax实现页面的局部刷新 一.不依赖jquery时是这样的用法: var xhr=new XMLHttpRequest(); xhr.onreadystatechange=function(ev ...