Internal Binder Connections for Android

I am working on a project where we add some non-standard security features to the Android system, and I have some serious problems for adapting Binder.

Does anyone have deep knowledge in the Binder system and know why Binder "blocks" the process of sending a parcel and how is the receiving process unlocked?

+4
source share
1 answer

This is the expected behavior from what the Android documentation says: 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 get a call included in the Binder object, respectively. This transaction API is synchronous, so the call to transaction () does not return until the target returns from Binder.onTransact (); this is the expected behavior when calling an object that exists in a local process and basic interprocess communication (IPC) ensures that these same semantics are applied when moving through processes.

Follow the notification API. We make some calls so that we can finally get a reference to the NotificationManager object. With this object, we call 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 } 

This call is synchronized with your process, and this will result in the following call:

  @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} 

See the call to 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} 

Now the method (from IBinder) mRemote.transact (Stub.TRANSACTION_enqueueNotification, _data, _reply, 0); will do magic. According to the Parcel class documentation:

A Parcel can contain both flattened data that will be peeled off on the other side of the IPC (using various methods for writing specific types or the general Parcelable interface), as well as links to live IBinder objects, which will cause the other side to receive IBinder proxies, connected to the original IBinder in the Park.

So, as soon as the other side receives the serialized data, it will respond accordingly. Thus, it blocks the calling process due to system design, so that development is more continuous, so as not to add complexity to application development and consistency. The receiving process is not blocked, it is a live IBinder object, and one of its threads responds to the request. Now, if an object is operating under high overhead, it may be possible to block for a long time before responding. Therefore, if you plan to talk with busy guys, make sure you have an assistant to keep waiting for an answer (another thread, pehaps).

\ about/

+1
source

Source: https://habr.com/ru/post/1435236/


All Articles