gpt4 book ai didi

Android Binder 内部

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:06:39 29 4
gpt4 key购买 nike

我正在做一个项目,我们向 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/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com