Android 安卓活页夹内部构件

Android 安卓活页夹内部构件,android,driver,android-binder,Android,Driver,Android Binder,我正在做一个项目,在这个项目中,我们向android系统添加了一些非标准的安全功能,我在调整活页夹时遇到了一些严重的问题 是否有人对活页夹系统有深入的了解,并且知道活页夹为什么“阻止”传送包裹的过程,以及接收过程如何被解锁?这是Android文档中所说的预期行为: 键IBinder API是由Binder.onTransact()匹配的transact()。 这些方法允许您向IBinder对象发送调用,并 分别接收传入绑定器对象的调用。这 事务API是同步的,因此对transact()的调用

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


是否有人对活页夹系统有深入的了解,并且知道活页夹为什么“阻止”传送包裹的过程,以及接收过程如何被解锁?

这是Android文档中所说的预期行为:

键IBinder API是由Binder.onTransact()匹配的transact()。 这些方法允许您向IBinder对象发送调用,并 分别接收传入绑定器对象的调用。这 事务API是同步的,因此对transact()的调用 在目标从Binder.onTransact()返回之前不返回; 这是调用中存在的对象时的预期行为 本地进程和底层进程间通信 (IPC)机制确保在运行时应用这些相同的语义 跨流程

遵守通知API。我们进行一些调用,以便最终获得对NotificationManager对象的引用。对于这个对象,我们称之为notify(…)

此调用与您的进程同步,并将导致以下调用:

 @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\u enqueueNotification,\u data,\u reply,0);我会变魔术的。根据关于地块类别的文件:

地块可以包含将在其上取消展平的两个展平数据 IPC的另一面(使用此处的各种写入方法 特定类型(或通用包裹接口)和参考 激活将导致另一侧接收到 代理IBinder与地块中的原始IBinder连接

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


\o/

阻塞和取消阻塞确实是由设计决定的-绑定器是“基于事务的”,但它实际上发生在IPCThreadState的较低级别上,IPCThreadState是保存绑定器数据的每个线程实例:

消息通过低级别驱动程序上的ioctl(2)操作发送/接收(通常为/dev/binder,但从8.0 vndbinder、hwbinder开始)。这使得调用者可以在一个逻辑操作中发送消息和接收回复,而不是像套接字那样执行两个系统调用(发送(2)/接收(2))

你的应用程序有一个绑定线程池(由ProcessState启动),Android服务也有一个绑定线程池(特别是system_server)。这就是为来自驱动程序的传入事务和BR_*代码提供服务的方式,这就是绑定器看似“异步”的特性是如何发生的——池处于休眠状态,但当传入通知(例如BR_DEAD_Binder)到达时,其中一个线程(您无法控制哪个线程)将被转换为Java回调(对于死亡通知,onBinderDied),在该线程中

这种设计使您可以轻松享受两个方面的最佳效果—在需要时看似异步的操作,以及在您想要提交“事务”时阻止发送/接收,这也有助于AIDL生成的代码从池中获取包裹,并在完成后将其回收

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}