Android 系统广播机制
一、Android应用程序注冊广播接收器(registerReceiver)的过程分析
參考Android应用程序注冊广播接收器(registerReceiver)的过程分析http://blog.csdn.net/luoshengyang/article/details/6737352和《Android系统源码情景分析》,作者罗升阳。
0、总图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamx0eGdjeQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
1、MainActivity和CounterService所在应用程序主线程向ActivityManagerService进程发送REGISTER_RECEIVER_TRANSACTION
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamx0eGdjeQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
如图:第一步
~/Android/frameworks/base/core/java/android/app
----ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager
{
...... public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver,
IntentFilter filter, String perm) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
Intent intent = null;
int haveIntent = reply.readInt();
if (haveIntent != 0) {
intent = Intent.CREATOR.createFromParcel(reply);
}
reply.recycle();
data.recycle();
return intent;
} ...... }
当中receiver为InnerReceiver对象,例如以下图。还要filter,主要关注这两个參数。
如图:第二步,省略binder_transaction传输过程,由于上面已经分析过了。
如图:第三步
~/Android/frameworks/base/core/java/android/app
----ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
......
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case REGISTER_RECEIVER_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app =
b != null ? ApplicationThreadNative.asInterface(b) : null;
b = data.readStrongBinder();
IIntentReceiver rec
= b != null ? IIntentReceiver.Stub.asInterface(b) : null;
IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
String perm = data.readString();
Intent intent = registerReceiver(app, rec, filter, perm);
reply.writeNoException();
if (intent != null) {
reply.writeInt(1);
intent.writeToParcel(reply, 0);
} else {
reply.writeInt(0);
}
return true;
}
.......
}
rec为IIntentReceiver.Stub.Proxy对象,如上图所看到的。还要filter,主要关注这两个參数。
如图:第四步
~/Android/frameworks/base/services/java/com/android/server/am
----ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
...... public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver, IntentFilter filter, String permission) {
synchronized(this) {
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
......
}
} .......
ReceiverList rl
= (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp,
Binder.getCallingPid(),
Binder.getCallingUid(), receiver); if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
......
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
} BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
rl.add(bf);
......
mReceiverResolver.addFilter(bf); // Enqueue broadcasts for all existing stickies that match
// this filter.
if (allSticky != null) {
......
} return sticky;
}
} ...... }
主要做了下面几件事:
(1)依据receiver创建ReceiverList。
(2)依据filter和rl创建BroadcastFilter。
(3)mReceiver.addFilter(bf)。
二、Android应用程序发送广播(sendBroadcast)的过程分析
0、总图
1、MainActivity和CounterService所在应用程序主线程向ActivityManagerService进程发送BROADCAST_INTENT_TRANSACTION
如图:第一步
~/Android/frameworks/base/core/java/android/app
----ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager
{
...... public int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized,
boolean sticky) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
data.writeInt(resultCode);
data.writeString(resultData);
data.writeBundle(map);
data.writeString(requiredPermission);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
reply.recycle();
data.recycle();
return res;
} ...... }
当中主要关注intent參数。
如图:第二步,省略binder_transaction传输过程。由于上面已经分析过了。
如图:第三步
~/Android/frameworks/base/core/java/android/app
----ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
......
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case BROADCAST_INTENT_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app =
b != null ? ApplicationThreadNative.asInterface(b) : null;
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
IIntentReceiver resultTo =
b != null ? IIntentReceiver.Stub.asInterface(b) : null;
int resultCode = data.readInt();
String resultData = data.readString();
Bundle resultExtras = data.readBundle();
String perm = data.readString();
boolean serialized = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
int res = broadcastIntent(app, intent, resolvedType, resultTo,
resultCode, resultData, resultExtras, perm,
serialized, sticky);
reply.writeNoException();
reply.writeInt(res);
return true;
}
.......
}
如图:第四步
~/Android/frameworks/base/services/java/com/android/server/am
----ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
...... public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky) {
synchronized(this) {
intent = verifyBroadcastLocked(intent); final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, serialized,
sticky, callingPid, callingUid);
Binder.restoreCallingIdentity(origId);
return res;
}
} ......
}
主要做了下面几件事:
(1)依据intent找出对应的广播接收器:
List<BroadcastFilter> registeredReceivers = null;
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
(2)依据intent(里面还包括数据)。registeredReceivers创建BroadcastRecord对象,并增加mParallelBroadcasts中:
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false);
mParallelBroadcasts.add(r);
(3)依据r和从r中得到的BroadcastFilter(即上面注冊时的BroadcastFilter),调用deliverToRegisteredReceiverLocked:
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
(4)调用filter.receiverList.receiver和new Intent(r.intent)调用performReceiveLocked:
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, r.ordered, r.initialSticky);
(5)ActivityManagerService进程向MainActivity和CounterService所在应用程序子线程发送SCHEDULE_REGISTERED_RECEIVER_TRANSACTION
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky);
当中receiver为IIntentReceiver.Stub.Proxy对象。intent为要传递的数据。
2、ActivityManagerService进程向MainActivity和CounterService所在应用程序子线程发送SCHEDULE_REGISTERED_RECEIVER_TRANSACTION
如图:第一步
~/Android/frameworks/base/core/java/android/app
----ApplicationThreadNative.java,ApplicationThreadProxy类
class ApplicationThreadProxy implements IApplicationThread {
...... public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(receiver.asBinder());
intent.writeToParcel(data, 0);
data.writeInt(resultCode);
data.writeString(dataStr);
data.writeBundle(extras);
data.writeInt(ordered ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
} ......
}
当中receiver为IIntentReceiver.Stub.Proxy对象,intent为要传递的数据。
如图:第二步,省略binder_transaction传输过程,由于上面已经分析过了。
如图:第三步
~/Android/frameworks/base/core/java/android/app
----ApplicationThreadNative.java
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread {
........
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case SCHEDULE_REGISTERED_RECEIVER_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
IIntentReceiver receiver = IIntentReceiver.Stub.asInterface(
data.readStrongBinder());
Intent intent = Intent.CREATOR.createFromParcel(data);
int resultCode = data.readInt();
String dataStr = data.readString();
Bundle extras = data.readBundle();
boolean ordered = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
scheduleRegisteredReceiver(receiver, intent,
resultCode, dataStr, extras, ordered, sticky);
return true;
}
.......
}
当中receiver为InnerReceiver。
intent为要传递的数据。
大家已经对,IIntentReceiver.Stub.asInterface( data.readStrongBinder())非常费解,data.readStrongBinder得到是InnerReceiver对象,那为什么要生成IIntentReceiver.Stub.Proxy的代理对象呢?事实上不然。绕了一圈,最后还是生成了InnerReceiver对象。
public static android.content.IIntentReceiver asInterface(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface) obj
.queryLocalInterface(DESCRIPTOR);//假设是BinderProxy对象调用这种方法。返回的NULL。可是如今是InnerReceiver,详细调用例如以下,返回的是IInterface
if (((iin != null) && (iin instanceof android.content.IIntentReceiver))) {
return ((android.content.IIntentReceiver) iin);
}
return new android.content.IIntentReceiver.Stub.Proxy(obj);
}
public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
如今是InnerReceiver,详细调用例如以下。返回的是IInterface。这个是在IIntentReceiver.Stub初始化时设置的。
public interface IIntentReceiver extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements
android.content.IIntentReceiver {
private static final java.lang.String DESCRIPTOR = "android.content.IIntentReceiver"; /** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
如图:第四步
~/Android/frameworks/base/core/java/android/app
----ActivityThread.java
public final class ActivityThread {
...... private final class ApplicationThread extends ApplicationThreadNative {
...... // This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky) throws RemoteException {
receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
} ......
} ...... }
经过一系列折腾,最后在MainActivity和CounterService所在应用程序主线程运行:
receiver.onReceive(mContext, intent);
运行onRecevice函数:
public class MainActivity extends Activity implements OnClickListener {
...... private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){
public void onReceive(Context context, Intent intent) {
int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);
String text = String.valueOf(counter);
counterText.setText(text); Log.i(LOG_TAG, "Receive counter event");
}
} ...... }
Android 系统广播机制的更多相关文章
- Android系统广播机制存在漏洞,恶意软件可绕过安全机制跟踪用户
前言 国外研究人员披露了Android漏洞(CVE-2018-9489)的信息.Android系统的内部广播机制会暴露敏感的用户和设备信息,手机上安装的应用可在用户不知情或未经许可的情况下访问获取这些 ...
- Android系统广播处理机制
Android系统中的广播是广泛用于应用程序之间通信的一种手段,它类似于事件处理机制,不同的地方就是广播的处理是系统级别的事件处理过程(一般事件处理是控件级别的).在此过程中仍然是离不开Intent对 ...
- Android广播机制的深入学习
部分内容转载自http://www.cnblogs.com/lwbqqyumidi/p/4168017.html 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者 ...
- Android总结篇系列:Android广播机制
1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通 ...
- Android广播机制概述
1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通 ...
- Android广播机制:Broadcast
转载:Android总结篇系列:Android广播机制 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广 ...
- Android广播机制(转)
1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通 ...
- Android广播机制
原文出处: Android总结篇系列:Android广播机制 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的 ...
- Android随笔之——Android广播机制Broadcast详解
在Android中,有一些操作完成以后,会发送广播,比如说发出一条短信,或打出一个电话,如果某个程序接收了这个广播,就会做相应的处理.这个广播跟我们传统意义中的电台广播有些相似之处.之所以叫做广播,就 ...
随机推荐
- day23 02 组合(继续人狗大战游戏)
day23 02 组合(继续人狗大战游戏) 面向对象的三大特性:继承 多态 封装 先讲解一下组合 组合:一个对象的属性值是另一个类的对象:对象.属性.属性(一般有两个点) 继续扩展day22 01里面 ...
- django第13天(auth组件,forms组件,中间件,csrf)
django第13天(auth组件,forms组件) auth组件 -auth组件 -auth是什么? -django内置的用户认证系统,可以快速的实现,登录,注销,修改密码.... -怎么用? -( ...
- Solr通过配DIH对数据库数据做索引
1 加入相关jar包 将2个相关jar包复制到/opt/solr-7.7.1/server/solr-webapp/webapp/WEB-INF/lib文件夹下 jar包名称 solr-dataimp ...
- mysql 与QT的连接
第一步:安装 qt开发环境 bi@bi-desktop:~$sudo apt-get install qt4-dev-tools qt4-doc qt4-qtconfig qt4-demos qt4- ...
- 03007_HttpServlet
1.创建 new---Servlet package com.gzdlh.servlet; import java.io.IOException; import javax.servlet.Servl ...
- 【01】git下载和安装的完整过程
[03]下载地址: 有许多种安装方式,主要分为两种,一种是通过编译源代码来安装:另一种是使用为特定平台预编译好的安装包. Git 各平台安装包下载地址为:http://git-scm.com/down ...
- 在 Yii2 项目中使用 Composer 添加 FontAwesome 字体资源
2014-06-21 19:05 原文 简体 繁體 2,123 次围观 前天帮同事改个十年前的网站 bug,页面上一堆 include require 不禁让人抱头痛哭.看到 V2EX 上的讨论说,写 ...
- BNUOJ 3580 Oulipo
Oulipo Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 3 ...
- Python --链接Mongodb
# -*- coding: UTF-8 -*- from pymongo import MongoClient # 数据库连接 class MongoDB(object): def __init__( ...
- SPOJ - DQUERY 主席树求区间有多少个不同的数(模板)
D-query Time Limit: 227MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Submit Status ...