草庐IT

Android Binder 内部

coder 2023-12-16 原文

我正在做一个项目,我们向 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 Binder 内部的更多相关文章

  1. ruby - 是否可以从也在该模块中的类内部调用模块函数 - 2

    在这段Ruby代码中:ModuleMClassC当我尝试运行时出现“'M:Module'的未定义方法'helper'”错误c=M::C.new("world")c.work但直接从另一个类调用M::helper("world")工作正常。类不能调用在定义它们的同一模块中定义的模块函数吗?除了将类移出模块外,还有其他解决方法吗? 最佳答案 为了调用M::helper,你需要将它定义为defself.helper;结束为了进行比较,请查看以下修改后的代码段中的helper和helper2moduleMclassC

  2. ruby - 无法安装 gem - make 未被识别为内部或外部命令可运行程序或批处理文件 - 2

    我想在Windows7上安装带有ruby​​1.9.3的rspec-railsgem。我收到一些错误消息,提示无法安装某些json库。所以,我使用下面的说明来解决它。来源=The'json'nativegemrequiresinstalledbuildtools从[rubyinstaller.org][3]下载[Ruby1.9.3][2]从[rubyinstaller.org][3]下载DevKit文件对于Ruby1.9.3,使用[DevKit-tdm-32-4.5.2-20110712-1620-sfx.exe][4]将DevKit解压到路径C:\Ruby193\DevKit运行cd

  3. ruby - 如何在 Ruby 中实现私有(private)内部类 - 2

    来自Java,我正在尝试在Ruby中实现LinkedList。我在Java中实现它的通常方法是有一个名为LinkedList的类和一个名为Node的私有(private)内部类,其中LinkedList的每个对象都作为Node对象。classLinkedListprivateclassNodeattr_accessor:val,:nextendend我不想将Node类暴露给外部世界。然而,通过Ruby中的这个设置,我可以使用这个访问LinkedList类之外的私有(private)Node类对象-node=LinkedList::Node.new我知道,在Ruby1.9中,我们可以使用

  4. ruby - Lisp 作为内部 Ruby DSL? - 2

    我已经能够找到:a)用Ruby编写的Lisp解释器(即外部DSL)http://onestepback.org/index.cgi/Tech/Ruby/LispInRuby.redb)作为RubyDSL的Prologhttp://www.kdedevelopers.org/node/2369c)讨论Ruby“作为”一个Lisphttp://www.randomhacks.net/articles/2005/12/03/why-ruby-is-an-acceptable-lisp但奇怪的是,我实际上找不到Lisp的“内部”实现,例如Prolog的实现。我只是不够谷歌,还是还没有人发表过这

  5. ruby - RVM screen 内部损坏 - 2

    我正在使用screen,甚至在rvm1.9.2之后并且有一个合适的.rvmrc我的服务器将仍然使用jruby。我的.screenrc包含shell#{SHELL}rvm信息显示jruby。好像rvm1.9.2没有任何效果,但它在screen外工作正常。 最佳答案 好的,我找到了solution.创建一个.screenrc文件并将此代码段放入其中:shell-$SHELLofficialinstructions省略破折号。 关于ruby-RVMscreen内部损坏,我们在StackOver

  6. ruby - 使用 YARD for Ruby 文档的内部评论? - 2

    我正在将我维护的ruby​​gem从RDoc切换到YARD文档。但是,代码中有一些关键注释只需要保留在代码中,不应出现在文档中。例如:###SomeClassdocumentationhere.#--#CRITICALcommentthatshouldbeinthecodebutnotinthedocumentation,#andmustbeatthisparticularspotinthecode.#++#moredocumentationthatfollowsthecriticalcommentblock,butthispart#shouldbeinthegenerateddocu

  7. Ruby - 从对象内部调用 setter - 2

    这个问题在这里已经有了答案:WhydoRubysettersneed"self."qualificationwithintheclass?(3个答案)关闭7年前。我一直在研究PragmaticProgrammers的“ProgrammingRuby”一书,想知道是否可以在类中调用setter方法,而不是直接分配给实例变量。classBookInStockattr_reader:isbn,:pricedefinitialize(isbn,price)@isbn=isbn@price=Float(price)enddefprice_in_centsInteger(price*100+0.5

  8. Ruby:是否有关键字可以从自身内部调用方法(类似于 super)? - 2

    我想知道:在Ruby中,有没有一种方法可以在不使用其名称的情况下从自身内部调用方法?如果该方法是通过某些元编程技术创建的,那么通过其名称调用它可能会难以阅读。即使对于通常定义的方法,如果您不确定它的好名字,或者如果它的名字很长,通过一些关键字(类似于super)从自身内部调用它可能会很方便。 最佳答案 您可以使用Kernel#__method__以Symbol形式返回当前方法的名称。与super不同,它不是关键字而是常规方法,因此您必须将它连同必需的参数一起传递给send方法才能调用该方法。这是__method__返回的内容:obj

  9. ruby - 如何从定义相同名称的模块内部访问ruby中的顶级实体 - 2

    在一个模块中,我有一个名为Process的类。moduleMProcess=Class.newProcess::wait(0)end这会引发NoMethodError。如何从模块内部访问顶级Process?如果不重命名我的类(class),这完全有可能吗? 最佳答案 ::Process.wait(0) 关于ruby-如何从定义相同名称的模块内部访问ruby中的顶级实体,我们在StackOverflow上找到一个类似的问题: https://stackoverf

  10. ruby - 如何从 eval 内部返回? - 2

    我有一个代码需要在eval中使用。有时我需要退出评估代码,但我的尝试会导致错误。例如:#expectedtosee1,2and5;not3nor4;andnoerrorseval"puts1;puts2;return;puts3;puts4"#=>Error:unexpectedreturnputs5我尝试了return、end、exit、break,但都没有成功。exit不会引发错误,但我没有得到5。(注意:我知道eval是邪恶的,但在这种情况下我需要使用它。) 最佳答案 谢谢大家,但我找到了最适合我的问题的解决方案:lambda

随机推荐