Android Binder 内部

标签 android driver android-binder

我正在做一个项目,我们向 android 系统添加了一些非标准的安全功能,但我在调整 Binder 时遇到了一些严重的问题。

有没有人对Binder系统有很深的了解,知道Binder为什么会“阻塞”一个传递Parcel的进程,接收进程又是如何解阻塞的?

最佳答案

这是 Android 文档中所说的预期行为: http://developer.android.com/reference/android/os/IBinder.html

The key IBinder API is transact() matched by Binder.onTransact(). These methods allow you to send a call to an IBinder object and receive a call coming in to a Binder object, respectively. This transaction API is synchronous, such that a call to transact() does not return until the target has returned from Binder.onTransact(); this is the expected behavior when calling an object that exists in the local process, and the underlying inter-process communication (IPC) mechanism ensures that these same semantics apply when going across processes.

观察通知 API。我们进行一些调用,以便最终获得对 NotificationManager 对象的引用。有了这个对象,我们调用 notify(...);

117    public void notify(String tag, int id, Notification notification)
118    {
119        int[] idOut = new int[1];
120        INotificationManager service = getService();
121        String pkg = mContext.getPackageName();
122        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
123        try {
124            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);
125            if (id != idOut[0]) {
126                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
127            }
128        } catch (RemoteException e) {
129        }
130    }

此调用与您的流程同步,并将在以下调用中产生结果:

 @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
38 {
39 switch (code)
40 {
...
46 case TRANSACTION_enqueueNotification:
47 {
48 data.enforceInterface(DESCRIPTOR);
49 java.lang.String _arg0;
50 _arg0 = data.readString();
51 int _arg1;
52 _arg1 = data.readInt();
53 android.app.Notification _arg2;
54 if ((0!=data.readInt())) {
55 _arg2 = android.app.Notification.CREATOR.createFromParcel(data);
56 }
57 else {
58 _arg2 = null;
59 }
60 int[] _arg3;
61 _arg3 = data.createIntArray();
62 this.enqueueNotification(_arg0, _arg1, _arg2, _arg3);
63 reply.writeNoException();
64 reply.writeIntArray(_arg3);
65 return true;
66 }
67 case TRANSACTION_cancelNotification:
68 {
...
169return super.onTransact(code, data, reply, flags);
170}

看到对 this.enqueueNotification 的调用了吗?

public void enqueueNotification(java.lang.String pkg, int id, android.app.Notification notification, int[] idReceived) throws android.os.RemoteException
188{
189android.os.Parcel _data = android.os.Parcel.obtain();
190android.os.Parcel _reply = android.os.Parcel.obtain();
191try {
192_data.writeInterfaceToken(DESCRIPTOR);
193_data.writeString(pkg);
194_data.writeInt(id);
195if ((notification!=null)) {
196_data.writeInt(1);
197notification.writeToParcel(_data, 0);
198}
199else {
200_data.writeInt(0);
201}
202_data.writeIntArray(idReceived);
203mRemote.transact(Stub.TRANSACTION_enqueueNotification, _data, _reply, 0);
204_reply.readException();
205_reply.readIntArray(idReceived);
206}
207finally {
208_reply.recycle();
209_data.recycle();
210}
211}

现在方法(来自 IBinder)mRemote.transact(Stub.TRANSACTION_enqueueNotification, _data, _reply, 0);会做魔术。根据 Parcel 类的文档:

A Parcel can contain both flattened data that will be unflattened on the other side of the IPC (using the various methods here for writing specific types, or the general Parcelable interface), and references to live IBinder objects that will result in the other side receiving a proxy IBinder connected with the original IBinder in the Parcel.

所以一旦对方收到序列化后的数据,就会做出相应的响应。因此,由于系统设计,它阻止了调用过程,让开发更加连续,不增加应用程序开发的复杂性和一致性。 接收进程未被阻塞,它是一个 Activity 的 IBinder 对象,其线程之一将响应请求。现在,如果该对象在繁重的开销下工作,它可能会在回答之前阻塞很长时间。因此,如果您打算与忙碌的人交谈,请确保您有一个助手可以一直等待回复(也许是另一个线程)。

\o/

关于Android Binder 内部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12509418/

相关文章:

android - camera.getPicture 如何使用 apache cordova 在 android 中工作?

我可以在 Linux 驱动程序中使用 C11 的 <stdatomic.h> 吗?还是必须使用内存屏障的 Linux 函数?

Android Binder 示例

android - 如何检查两个Android Binder 代理对象是否相等?

java - 何时调用 Parcel.recycle()?

java - 测试 Android LVL,许可证检查总是因没有网络而失败

android - 如何在 mac osx 中将 .dex 转换为 .jar

android - Android ListView 和 DB

installation - 使用 Wix 安装 32 位和 64 位驱动程序?

mongodb - 如何使用struct使用mongo-go-driver的更新功能