Android跨進(jìn)程通信IPC整體內(nèi)容如下
- 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)
- 2家浇、Android跨進(jìn)程通信IPC之2——Bionic
- 3、Android跨進(jìn)程通信IPC之3——關(guān)于"JNI"的那些事
- 4玻墅、Android跨進(jìn)程通信IPC之4——AndroidIPC基礎(chǔ)1
- 4装诡、Android跨進(jìn)程通信IPC之4——AndroidIPC基礎(chǔ)2
- 5、Android跨進(jìn)程通信IPC之5——Binder的三大接口
- 6圈膏、Android跨進(jìn)程通信IPC之6——Binder框架
- 7塔猾、Android跨進(jìn)程通信IPC之7——Binder相關(guān)結(jié)構(gòu)體簡介
- 8、Android跨進(jìn)程通信IPC之8——Binder驅(qū)動(dòng)
- 9稽坤、Android跨進(jìn)程通信IPC之9——Binder之Framework層C++篇1
- 9丈甸、Android跨進(jìn)程通信IPC之9——Binder之Framework層C++篇2
- 10、Android跨進(jìn)程通信IPC之10——Binder之Framework層Java篇
- 11尿褪、Android跨進(jìn)程通信IPC之11——AIDL
- 12睦擂、Android跨進(jìn)程通信IPC之12——Binder補(bǔ)充
- 13、Android跨進(jìn)程通信IPC之13——Binder總結(jié)
- 14茫多、Android跨進(jìn)程通信IPC之14——其他IPC方式
- 15祈匙、Android跨進(jìn)程通信IPC之15——感謝
本片文章的主要目的是讓大家對Binder有個(gè)初步的了解,既然是初步了解,肯定所是以源碼上的注釋為主夺欲,讓大家對Binder有一個(gè)更直觀的認(rèn)識跪帝。PS:大部分注釋我是寫在類里面了, 重要的我會(huì)單獨(dú)的拿出來些阅。
主要內(nèi)容如下:
1伞剑、IInterface
2、IBinder
3市埋、Binder與BinderProxy類
4黎泣、總結(jié)
一、IInterface
/**
* Base class for Binder interfaces. When defining a new interface,
* you must derive it from IInterface.
*/
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}
(一)缤谎、類注釋
簡單的翻譯一下:
IInterface是Binder中相關(guān)接口的基類抒倚。 定義新接口的時(shí)候,你必須從IInterface派生坷澡。
(二)托呕、抽象方法注釋
如果想獲取和該接口關(guān)聯(lián)的Binder對象。你必須使用這個(gè)方法來而不是使用一個(gè)簡單的類型轉(zhuǎn)化频敛。這樣代理對象才能返回正確的結(jié)果
(三)项郊、總結(jié)
所以可以這樣說IInterface接口提供了類型轉(zhuǎn)化的功能凡橱,將服務(wù)或者服務(wù)代理類轉(zhuǎn)為IBinder類型辆沦。其實(shí)實(shí)際的類型轉(zhuǎn)換是由BnInterface隧饼、BpInterface兩個(gè)類完成的抹估,BnInterface將服務(wù)類轉(zhuǎn)換成IBinder類型抚笔,而BpInterface則將代理服務(wù)類轉(zhuǎn)換成IBinder類型苟翻。在通過Binder Driver傳遞Binder對象時(shí)衰倦,必須進(jìn)行類型轉(zhuǎn)換花鹅,比如在想系統(tǒng)注冊服務(wù)時(shí)食绿,需要先將服務(wù)類型轉(zhuǎn)換成IBinder侈咕,在其傳遞給Context Manager。
二器紧、IBinder
/**
* Base interface for a remotable object, the core part of a lightweight
* remote procedure call mechanism designed for high performance when
* performing in-process and cross-process calls. This
* interface describes the abstract protocol for interacting with a
* remotable object. Do not implement this interface directly, instead
* extend from {@link Binder}.
*
* <p>The key IBinder API is {@link #transact transact()} matched by
* {@link Binder#onTransact 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 {@link #transact transact()} does not
* return until the target has returned from
* {@link Binder#onTransact 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.
*
* <p>The data sent through transact() is a {@link Parcel}, a generic buffer
* of data that also maintains some meta-data about its contents. The meta
* data is used to manage IBinder object references in the buffer, so that those
* references can be maintained as the buffer moves across processes. This
* mechanism ensures that when an IBinder is written into a Parcel and sent to
* another process, if that other process sends a reference to that same IBinder
* back to the original process, then the original process will receive the
* same IBinder object back. These semantics allow IBinder/Binder objects to
* be used as a unique identity (to serve as a token or for other purposes)
* that can be managed across processes.
*
* <p>The system maintains a pool of transaction threads in each process that
* it runs in. These threads are used to dispatch all
* IPCs coming in from other processes. For example, when an IPC is made from
* process A to process B, the calling thread in A blocks in transact() as
* it sends the transaction to process B. The next available pool thread in
* B receives the incoming transaction, calls Binder.onTransact() on the target
* object, and replies with the result Parcel. Upon receiving its result, the
* thread in process A returns to allow its execution to continue. In effect,
* other processes appear to use as additional threads that you did not create
* executing in your own process.
*
* <p>The Binder system also supports recursion across processes. For example
* if process A performs a transaction to process B, and process B while
* handling that transaction calls transact() on an IBinder that is implemented
* in A, then the thread in A that is currently waiting for the original
* transaction to finish will take care of calling Binder.onTransact() on the
* object being called by B. This ensures that the recursion semantics when
* calling remote binder object are the same as when calling local objects.
*
* <p>When working with remote objects, you often want to find out when they
* are no longer valid. There are three ways this can be determined:
* <ul>
* <li> The {@link #transact transact()} method will throw a
* {@link RemoteException} exception if you try to call it on an IBinder
* whose process no longer exists.
* <li> The {@link #pingBinder()} method can be called, and will return false
* if the remote process no longer exists.
* <li> The {@link #linkToDeath linkToDeath()} method can be used to register
* a {@link DeathRecipient} with the IBinder, which will be called when its
* containing process goes away.
* </ul>
*
* @see Binder
*/
public interface IBinder {
/**
* The first transaction code available for user commands.
* 第一個(gè)可用于用戶命令的事務(wù)代碼耀销。
*/
int FIRST_CALL_TRANSACTION = 0x00000001;
/**
* The last transaction code available for user commands.
* 最后一個(gè)可用于用戶命令的事務(wù)代碼。
*/
int LAST_CALL_TRANSACTION = 0x00ffffff;
/**
* IBinder protocol transaction code: pingBinder().
* IBinder協(xié)議事物碼:在pingBinder()會(huì)用到
*/
int PING_TRANSACTION = ('_'<<24)|('P'<<16)|('N'<<8)|'G';
/**
* IBinder protocol transaction code: dump internal state.
* IBinder協(xié)議事物碼: 代表清除內(nèi)部狀態(tài)
*/
int DUMP_TRANSACTION = ('_'<<24)|('D'<<16)|('M'<<8)|'P';
/**
* IBinder protocol transaction code: execute a shell command.
* IBinder協(xié)議事物碼:代表執(zhí)行一個(gè)shell命令
* @hide
*/
int SHELL_COMMAND_TRANSACTION = ('_'<<24)|('C'<<16)|('M'<<8)|'D';
/**
* IBinder protocol transaction code: interrogate the recipient side
* of the transaction for its canonical interface descriptor.
* IBinder協(xié)議事物碼:代表詢問被調(diào)用方的接口描述符號
*/
int INTERFACE_TRANSACTION = ('_'<<24)|('N'<<16)|('T'<<8)|'F';
/**
* IBinder protocol transaction code: send a tweet to the target
* object. The data in the parcel is intended to be delivered to
* a shared messaging service associated with the object; it can be
* anything, as long as it is not more than 130 UTF-8 characters to
* conservatively fit within common messaging services. As part of
* {@link Build.VERSION_CODES#HONEYCOMB_MR2}, all Binder objects are
* expected to support this protocol for fully integrated tweeting
* across the platform. To support older code, the default implementation
* logs the tweet to the main log as a simple emulation of broadcasting
* it publicly over the Internet.
*
* <p>Also, upon completing the dispatch, the object must make a cup
* of tea, return it to the caller, and exclaim "jolly good message
* old boy!".
* IBinder協(xié)議事物碼:向目標(biāo)對象發(fā)出一個(gè)呼叫铲汪。在parcel中的數(shù)據(jù)是用于
* 分發(fā)一個(gè)與對象結(jié)合的共享信息服務(wù)熊尉。它可以是任何東西,只要它不超
* 過130個(gè)UTF-8字符掌腰,保證適用于常見的信息服務(wù)狰住。 作為
* Build.VERSION_CODES#HONEYCOMB_MR2的一部分,所有的binder
* 對象都支持這個(gè)協(xié)議齿梁,為了在跨平臺間完整推送同時(shí)也為了支持舊的交
* 互碼催植,一個(gè)默認(rèn)的實(shí)現(xiàn)是在主日志中記錄了一個(gè)推送肮蛹,作為廣播的一個(gè)
* 簡單模仿。
* 并且创南,為了完成消息的派送伦忠,對象必須返回給調(diào)用者一個(gè)說明,
* 表明是舊的信息稿辙。
*/
int TWEET_TRANSACTION = ('_'<<24)|('T'<<16)|('W'<<8)|'T';
/**
* IBinder protocol transaction code: tell an app asynchronously that the
* caller likes it. The app is responsible for incrementing and maintaining
* its own like counter, and may display this value to the user to indicate the
* quality of the app. This is an optional command that applications do not
* need to handle, so the default implementation is to do nothing.
*
* <p>There is no response returned and nothing about the
* system will be functionally affected by it, but it will improve the
* app's self-esteem.
* IBinder協(xié)議事物碼:異步地告訴app 有一個(gè)調(diào)用者在呼叫它昆码。這個(gè)app負(fù)
* 責(zé)計(jì)算和維護(hù)自己的呼叫者數(shù)目。 并且可以展示這個(gè)值來告訴用戶app
* 的狀態(tài)邻储。這個(gè)是可選的命令赋咽,app不需要掌管它,所以默認(rèn)是實(shí)現(xiàn)是什
* 么都不做吨娜。
* 這是沒有響應(yīng)的脓匿,并且不會(huì)對系統(tǒng)帶來影響,但是它提高了app的自控
* (我真的不知道怎么翻譯宦赠,elf-esteem其實(shí)是自尊的意思)
*/
int LIKE_TRANSACTION = ('_'<<24)|('L'<<16)|('I'<<8)|'K';
/** @hide */
//隱藏的API
int SYSPROPS_TRANSACTION = ('_'<<24)|('S'<<16)|('P'<<8)|'R';
/**
* Flag to {@link #transact}: this is a one-way call, meaning that the
* caller returns immediately, without waiting for a result from the
* callee. Applies only if the caller and callee are in different
* processes.
* 用于transact()方法中的flag亦镶,表示單向RPC,表明呼叫者會(huì)馬上返回袱瓮,
* 不必等結(jié)果從被呼叫者返回。只有當(dāng)呼叫者和被呼叫者在不同的進(jìn)程中
* 才有效.
*/
int FLAG_ONEWAY = 0x00000001;
/**
* Limit that should be placed on IPC sizes to keep them safely under the
* transaction buffer limit.
* @hide
* 為了讓其安全地保持在事物緩沖區(qū)限制之下爱咬,應(yīng)該限制IPC的大小
* 隱藏的API
*/
public static final int MAX_IPC_SIZE = 64 * 1024;
/**
* Get the canonical name of the interface supported by this binder.
* 獲取一個(gè)支持binder的接口規(guī)范名稱
*/
public String getInterfaceDescriptor() throws RemoteException;
/**
* Check to see if the object still exists.
*
* @return Returns false if the
* hosting process is gone, otherwise the result (always by default
* true) returned by the pingBinder() implementation on the other
* side.
* 檢查對象是否仍然存在尺借。
* 如果返回false,主機(jī)進(jìn)程消失精拟,否則結(jié)果為true(始終默認(rèn)true)由對
* 手方來實(shí)現(xiàn)pingBinder()這個(gè)方法燎斩。
*/
public boolean pingBinder();
/**
* Check to see if the process that the binder is in is still alive.
*
* @return false if the process is not alive. Note that if it returns
* true, the process may have died while the call is returning.
* 檢查該binder所在的進(jìn)程是否仍然存在
* 如果進(jìn)程不存在,則返回false蜂绎。 請注意栅表,如果返回true,則調(diào)用返回時(shí)
* 進(jìn)程可能已經(jīng)死機(jī)师枣。
*/
public boolean isBinderAlive();
/**
* Attempt to retrieve a local implementation of an interface
* for this Binder object. If null is returned, you will need
* to instantiate a proxy class to marshall calls through
* the transact() method.
*/
public IInterface queryLocalInterface(String descriptor);
/**
* Print the object's state into the given stream.
*
* @param fd The raw file descriptor that the dump is being sent to.
* @param args additional arguments to the dump request.
*/
public void dump(FileDescriptor fd, String[] args) throws RemoteException;
/**
* Like {@link #dump(FileDescriptor, String[])} but always executes
* asynchronously. If the object is local, a new thread is created
* to perform the dump.
*
* @param fd The raw file descriptor that the dump is being sent to.
* @param args additional arguments to the dump request.
*/
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
/**
* Execute a shell command on this object. This may be performed asynchrously from the caller;
* the implementation must always call resultReceiver when finished.
*
* @param in The raw file descriptor that an input data stream can be read from.
* @param out The raw file descriptor that normal command messages should be written to.
* @param err The raw file descriptor that command error messages should be written to.
* @param args Command-line arguments.
* @param resultReceiver Called when the command has finished executing, with the result code.
* @hide
*/
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ResultReceiver resultReceiver) throws RemoteException;
/**
* Perform a generic operation with the object.
*
* @param code The action to perform. This should
* be a number between {@link #FIRST_CALL_TRANSACTION} and
* {@link #LAST_CALL_TRANSACTION}.
* @param data Marshalled data to send to the target. Must not be null.
* If you are not sending any data, you must create an empty Parcel
* that is given here.
* @param reply Marshalled data to be received from the target. May be
* null if you are not interested in the return value.
* @param flags Additional operation flags. Either 0 for a normal
* RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
*/
public boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException;
/**
* Interface for receiving a callback when the process hosting an IBinder
* has gone away.
*
* @see #linkToDeath
*/
public interface DeathRecipient {
public void binderDied();
}
/**
* Register the recipient for a notification if this binder
* goes away. If this binder object unexpectedly goes away
* (typically because its hosting process has been killed),
* then the given {@link DeathRecipient}'s
* {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
* will be called.
*
* <p>You will only receive death notifications for remote binders,
* as local binders by definition can't die without you dying as well.
*
* @throws RemoteException if the target IBinder's
* process has already died.
*
* @see #unlinkToDeath
*/
public void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
/**
* Remove a previously registered death notification.
* The recipient will no longer be called if this object
* dies.
*
* @return {@code true} if the <var>recipient</var> is successfully
* unlinked, assuring you that its
* {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
* will not be called; {@code false} if the target IBinder has already
* died, meaning the method has been (or soon will be) called.
*
* @throws java.util.NoSuchElementException if the given
* <var>recipient</var> has not been registered with the IBinder, and
* the IBinder is still alive. Note that if the <var>recipient</var>
* was never registered, but the IBinder has already died, then this
* exception will <em>not</em> be thrown, and you will receive a false
* return value instead.
*/
public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}
注釋有點(diǎn)多怪瓶,我們一個(gè)一個(gè)來
(一)、類注釋
簡單的翻譯一下:
- 一個(gè)遠(yuǎn)程對象的基接口践美,是為高性能而設(shè)計(jì)的輕量級遠(yuǎn)程調(diào)用機(jī)制的核心部分洗贰,它不僅用于遠(yuǎn)程調(diào)用,也可以用于進(jìn)程內(nèi)調(diào)用陨倡。這個(gè)接口描述了與遠(yuǎn)程對象進(jìn)行交互的抽象協(xié)議敛滋。建議繼承Binder類,而不是直接實(shí)現(xiàn)這個(gè)接口兴革。
IBinder的主要API是transact()绎晃,與它對應(yīng)另一個(gè)方法是Binder.onTransact蜜唾。第一個(gè)方法使你可以向遠(yuǎn)端的IBinder對象發(fā)送調(diào)用,第二個(gè)方法使你自己的遠(yuǎn)程對象能夠響應(yīng)接收到的調(diào)用庶艾。IBinder的API都是同步執(zhí)行的袁余,比如transact()直到對方的Binder.onTransact()方法調(diào)用完成后才返回。而在跨進(jìn)程的時(shí)候落竹,在IPC的幫助下泌霍,也是同樣的效果。
通過transact()發(fā)送的數(shù)據(jù)是Parcel述召,Parcel是一種一般的緩沖區(qū)朱转,除了有數(shù)據(jù)外還帶有一些描述它內(nèi)容的元數(shù)據(jù)。元數(shù)據(jù)用于管理IBinder對象的引用积暖,這樣就能在緩沖去從一個(gè)進(jìn)程移動(dòng)到另一個(gè)進(jìn)程時(shí)藤为,保存這些引用。這樣就保證了當(dāng)一個(gè)IBinder被寫入到Parcel并發(fā)送到另一個(gè)進(jìn)程中夺刑,如果另一個(gè)進(jìn)程把同一個(gè)IBinder的引用回發(fā)到原來的進(jìn)程缅疟,那么這個(gè)原來的進(jìn)程就能接收到發(fā)出的那個(gè)IBinder的引用。這種機(jī)制使IBinder和Binder像唯一標(biāo)志符那樣在進(jìn)程間管理遍愿。
系統(tǒng)為每一個(gè)進(jìn)程維持一個(gè)存放交互的線程池存淫。這些交互的線程用于派發(fā)所有從其他進(jìn)程發(fā)來的IPC調(diào)用。例如:當(dāng)一個(gè)IPC從進(jìn)程A發(fā)到進(jìn)程B沼填,A中那個(gè)發(fā)出調(diào)用的線程就阻塞在transact()中了桅咆。進(jìn)程B中的交互線程池的一個(gè)線程池接收了這個(gè)調(diào)用,它調(diào)用Binder.onTransact()坞笙,完成后用一個(gè)Parcel來作為結(jié)果返回岩饼。然后進(jìn)程A中的那個(gè)等待線程在收到返回的Parcel才能繼續(xù)執(zhí)行。實(shí)際上薛夜,另一個(gè)進(jìn)程看起來就像當(dāng)前進(jìn)程的一個(gè)線程籍茧,但不是當(dāng)前進(jìn)程創(chuàng)建的。
Binder機(jī)制還支持進(jìn)程間的遞歸調(diào)用梯澜。例如寞冯,進(jìn)程A執(zhí)行自己的IBinder的transact()調(diào)用進(jìn)程B的Binder,而進(jìn)程B在其Binder.onTransact()中又用transact()向進(jìn)程A發(fā)起調(diào)用,那么進(jìn)程A在等待它發(fā)布出的調(diào)用返回的同時(shí)晚伙,還會(huì)用Binder.onTransact()響應(yīng)進(jìn)程B的transact()简十。總之撬腾,Binder造成的結(jié)果就是讓我們感覺到跨進(jìn)程的調(diào)用與進(jìn)程內(nèi)的調(diào)用沒有什么區(qū)別螟蝙。
當(dāng)操作遠(yuǎn)程對象的時(shí)候,你需要經(jīng)常查看它們是否有效民傻,有3種方法可以使用:
- 1 transact()方法將在IBinder所在的進(jìn)程不存在時(shí)拋出RemoteException異常
- 2 如果目標(biāo)進(jìn)程不存在胰默,那么調(diào)用pingBinder()時(shí)返回false\
- 3 可以用linkToDeath()方法向IBinder注冊一個(gè)IBinder.DeathRecipient场斑,在IBinder代表的進(jìn)程退出時(shí)被調(diào)用。
(二)牵署、重要方法注釋
1漏隐、queryLocalInterface(String descriptor) 方法
/**
* Attempt to retrieve a local implementation of an interface
* for this Binder object. If null is returned, you will need
* to instantiate a proxy class to marshall calls through
* the transact() method.
*/
public IInterface queryLocalInterface(String descriptor);
翻譯如下:
用于接收一個(gè)用于當(dāng)前binder對象的本地接口的實(shí)現(xiàn)。如果返回null奴迅,你需要通過transact()方法去實(shí)例化一個(gè)代理類青责。
2、dump(FileDescriptor fd, String[] args) 方法
/**
* Print the object's state into the given stream.
*
* @param fd The raw file descriptor that the dump is being sent to.
* @param args additional arguments to the dump request.
*/
public void dump(FileDescriptor fd, String[] args) throws RemoteException;
翻譯如下:
將對象狀態(tài)打印入給定的數(shù)據(jù)流中.
- 入?yún)d:轉(zhuǎn)儲(chǔ)發(fā)送到的原始文件描述符取具。
- 入?yún)rgs: 轉(zhuǎn)儲(chǔ)請求的附加參數(shù)
3脖隶、dumpAsync(FileDescriptor fd, String[] args) 方法
/**
* Like {@link #dump(FileDescriptor, String[])} but always executes
* asynchronously. If the object is local, a new thread is created
* to perform the dump.
*
* @param fd The raw file descriptor that the dump is being sent to.
* @param args additional arguments to the dump request.
*/
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
翻譯如下:
類似dump(FileDescriptor, String[])方法,但是總是異步執(zhí)行暇检。如果對象在本地产阱, 一個(gè)新的線程將會(huì)被創(chuàng)建去執(zhí)行這個(gè)操作。
- 入?yún)d:轉(zhuǎn)儲(chǔ)發(fā)送到的原始文件描述符块仆。
- 入?yún)rgs: 轉(zhuǎn)儲(chǔ)請求的附加參數(shù)
4构蹬、shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,String[] args, ResultReceiver resultReceiver) 方法
/**
* Execute a shell command on this object. This may be performed asynchrously from the caller;
* the implementation must always call resultReceiver when finished.
*
* @param in The raw file descriptor that an input data stream can be read from.
* @param out The raw file descriptor that normal command messages should be written to.
* @param err The raw file descriptor that command error messages should be written to.
* @param args Command-line arguments.
* @param resultReceiver Called when the command has finished executing, with the result code.
* @hide
*/
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,String[] args, ResultReceiver resultReceiver) throws RemoteException;
翻譯如下:
對此對象執(zhí)行shell命令。 可以異步執(zhí)行; 執(zhí)行完畢后必須始終調(diào)用resultReceiver悔据。
- 入?yún)n:可以讀取輸入數(shù)據(jù)流的原始文件描述符庄敛。
- 入?yún)ut: 正常命令消息應(yīng)寫入的原始文件描述符。
- 入?yún)rr:命令錯(cuò)誤消息應(yīng)寫入的原始文件描述符科汗。
- 入?yún)rgs: 命令行參數(shù)铐姚。
- 入?yún)esultReceiver: 當(dāng)命令執(zhí)行結(jié)束后,使用結(jié)果代碼調(diào)用肛捍。
5、transact(int code, Parcel data, Parcel reply, int flags)方法
/**
* Perform a generic operation with the object.
*
* @param code The action to perform. This should
* be a number between {@link #FIRST_CALL_TRANSACTION} and
* {@link #LAST_CALL_TRANSACTION}.
* @param data Marshalled data to send to the target. Must not be null.
* If you are not sending any data, you must create an empty Parcel
* that is given here.
* @param reply Marshalled data to be received from the target. May be
* null if you are not interested in the return value.
* @param flags Additional operation flags. Either 0 for a normal
* RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
*/
public boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException;
翻譯如下:
對對象執(zhí)行一個(gè)通用的操作
- 入?yún)ode:操作碼必須在FIRST_CALL_TRANSACTION和LAST_CALL_TRANSACTION之間
- 入?yún)ata: 傳輸給目標(biāo)的數(shù)據(jù)之众。如果你沒有傳輸任何數(shù)據(jù)拙毫,你必須創(chuàng)建一個(gè)空的Parcel
- 入?yún)eply:從目標(biāo)接收的數(shù)據(jù)」缀蹋可以是null如果你對返回的值不感興趣缀蹄。
- 入?yún)lags: 附加操作標(biāo)志。0是指普通的RPC膘婶∪鼻埃或者FLAG_ONEWAY,指單向RPC悬襟。
6衅码、linkToDeath(DeathRecipient recipient, int flags)方法
/**
* Register the recipient for a notification if this binder
* goes away. If this binder object unexpectedly goes away
* (typically because its hosting process has been killed),
* then the given {@link DeathRecipient}'s
* {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
* will be called.
*
* <p>You will only receive death notifications for remote binders,
* as local binders by definition can't die without you dying as well.
*
* @throws RemoteException if the target IBinder's
* process has already died.
*
* @see #unlinkToDeath
*/
public void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
翻譯如下:
注冊一個(gè)recipient用于提示binder消失。如果binder對象異常地消失(例如由于主進(jìn)程被殺)脊岳,DeathRecipient中的binderDied會(huì)被調(diào)用.
7逝段、unlinkToDeath(DeathRecipient recipient, int flags)方法
/**
* Remove a previously registered death notification.
* The recipient will no longer be called if this object
* dies.
*
* @return {@code true} if the <var>recipient</var> is successfully
* unlinked, assuring you that its
* {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
* will not be called; {@code false} if the target IBinder has already
* died, meaning the method has been (or soon will be) called.
*
* @throws java.util.NoSuchElementException if the given
* <var>recipient</var> has not been registered with the IBinder, and
* the IBinder is still alive. Note that if the <var>recipient</var>
* was never registered, but the IBinder has already died, then this
* exception will <em>not</em> be thrown, and you will receive a false
* return value instead.
*/
public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}
翻譯如下:
刪除以前注冊的死亡通知垛玻。 如果對象死亡,則recipient不再會(huì)被調(diào)用
(三)奶躯、內(nèi)部接口注釋
1帚桩、DeathRecipient(int code, Parcel data, Parcel reply, int flags)方法
/**
* Interface for receiving a callback when the process hosting an IBinder
* has gone away.
*
* @see #linkToDeath
*/
public interface DeathRecipient {
public void binderDied();
}
翻譯如下:
當(dāng)持有IBinder進(jìn)程消失,會(huì)回調(diào)這個(gè)接口
(四)嘹黔、總結(jié):
通過上面對IBinder注釋账嚎,我們大概可以知道以下信息
- 1、IBindre是遠(yuǎn)程對象的基接口儡蔓,不僅可以在跨進(jìn)程可以調(diào)用郭蕉,也可以在進(jìn)程內(nèi)部調(diào)用
- 2、在遠(yuǎn)程調(diào)用的時(shí)候浙值,一端用IBinder.transact()發(fā)送恳不,另一端用Binder的Binder.onTransact()接受,并且是同步的
- 3开呐、transact()方法發(fā)送的是Parcel烟勋。
- 4、系統(tǒng)為每個(gè)進(jìn)程維護(hù)一個(gè)進(jìn)行跨進(jìn)程調(diào)用的線程池筐付。
- 5卵惦、可以使用pingBinder()方法來檢測目標(biāo)進(jìn)程是否存在
- 6、可以調(diào)用linkToDeath()來向IBinder注冊一個(gè)IBinder.DeathRecipien瓦戚。用于目標(biāo)進(jìn)程退出時(shí)候的提醒沮尿。
- 7、建議繼承Binder類较解,而不是直接實(shí)現(xiàn)這個(gè)接口畜疾。
三、Binder與BinderProxy類
(一)印衔、Binder
/**
* Base class for a remotable object, the core part of a lightweight
* remote procedure call mechanism defined by {@link IBinder}.
* This class is an implementation of IBinder that provides
* standard local implementation of such an object.
*
* <p>Most developers will not implement this class directly, instead using the
* <a href="{@docRoot}guide/components/aidl.html">aidl</a> tool to describe the desired
* interface, having it generate the appropriate Binder subclass. You can,
* however, derive directly from Binder to implement your own custom RPC
* protocol or simply instantiate a raw Binder object directly to use as a
* token that can be shared across processes.
*
* <p>This class is just a basic IPC primitive; it has no impact on an application's
* lifecycle, and is valid only as long as the process that created it continues to run.
* To use this correctly, you must be doing so within the context of a top-level
* application component (a {@link android.app.Service}, {@link android.app.Activity},
* or {@link android.content.ContentProvider}) that lets the system know your process
* should remain running.</p>
*
* <p>You must keep in mind the situations in which your process
* could go away, and thus require that you later re-create a new Binder and re-attach
* it when the process starts again. For example, if you are using this within an
* {@link android.app.Activity}, your activity's process may be killed any time the
* activity is not started; if the activity is later re-created you will need to
* create a new Binder and hand it back to the correct place again; you need to be
* aware that your process may be started for another reason (for example to receive
* a broadcast) that will not involve re-creating the activity and thus run its code
* to create a new Binder.</p>
*
* @see IBinder
*/
public class Binder implements IBinder {
/*
* Set this flag to true to detect anonymous, local or member classes
* that extend this Binder class and that are not static. These kind
* of classes can potentially create leaks.
* 通過設(shè)置這個(gè)標(biāo)記來檢測是否是Binder的匿名內(nèi)部類啡捶,或者Binder的
* 本地內(nèi)部類,因?yàn)檫@些類可能會(huì)存在潛在的內(nèi)存泄露 handler里面也
* 有這段話哦~
*/
private static final boolean FIND_POTENTIAL_LEAKS = false;
private static final boolean CHECK_PARCEL_SIZE = false;
static final String TAG = "Binder";
/** @hide */
public static boolean LOG_RUNTIME_EXCEPTION = false; // DO NOT SUBMIT WITH TRUE
/**
* Control whether dump() calls are allowed.
* 控制是否允許dump()方法的調(diào)用奸焙。
*/
private static String sDumpDisabled = null;
/**
* Global transaction tracker instance for this process.
* 進(jìn)程的全局事務(wù)跟蹤器實(shí)例瞎暑。
*/
private static TransactionTracker sTransactionTracker = null;
// Transaction tracking code.
// 事務(wù)跟蹤代碼
/**
* Flag indicating whether we should be tracing transact calls.
* 標(biāo)志, 表示我們是否應(yīng)該跟蹤事務(wù)調(diào)用与帆。
*/
private static boolean sTracingEnabled = false;
/**
* Enable Binder IPC tracing.
* 啟動(dòng) Binder IPC 跟蹤
* @hide
*/
public static void enableTracing() {
sTracingEnabled = true;
};
/**
* Disable Binder IPC tracing.
* 關(guān)閉 Binder IPC 跟蹤
* @hide
*/
public static void disableTracing() {
sTracingEnabled = false;
}
/**
* Check if binder transaction tracing is enabled.
* 檢查 Binder的事務(wù)跟蹤是否已啟用
* @hide
*/
public static boolean isTracingEnabled() {
return sTracingEnabled;
}
/**
* Get the binder transaction tracker for this process.
* 獲取此進(jìn)程的 Binder 事務(wù)跟蹤器了赌。
* @hide
*/
public synchronized static TransactionTracker getTransactionTracker() {
if (sTransactionTracker == null)
sTransactionTracker = new TransactionTracker();
return sTransactionTracker;
}
/* mObject is used by native code, do not remove or rename */
// mObject 會(huì)被Native 代碼調(diào)用,不要?jiǎng)h除或重命名
private long mObject;
private IInterface mOwner;
private String mDescriptor;
/**
* Return the ID of the process that sent you the current transaction
* that is being processed. This pid can be used with higher-level
* system services to determine its identity and check permissions.
* If the current thread is not currently executing an incoming transaction,
* then its own pid is returned.
* 返回向您發(fā)送正在處理的當(dāng)前事務(wù)的進(jìn)程的ID玄糟。 該pid可以與更高級
* 別的系統(tǒng)服務(wù)一起使用勿她,以確定其身份和檢查權(quán)限。 如果當(dāng)前線程當(dāng)
* 前沒有執(zhí)行傳入事務(wù)阵翎,則返回其自己的pid嫂拴。
*/
public static final native int getCallingPid();
/**
* Return the Linux uid assigned to the process that sent you the
* current transaction that is being processed. This uid can be used with
* higher-level system services to determine its identity and check
* permissions. If the current thread is not currently executing an
* incoming transaction, then its own uid is returned.
* 將分配給您的Linux uid返回給向您發(fā)送正在處理的當(dāng)前事務(wù)的進(jìn)程播揪。
* 這個(gè)uid可以與更高級別的系統(tǒng)服務(wù)一起使用,以確定其身份和檢查
* 權(quán)限筒狠。 如果當(dāng)前線程當(dāng)前沒有執(zhí)行傳入事務(wù)猪狈,則返回其自己的uid。
*/
public static final native int getCallingUid();
/**
* Return the UserHandle assigned to the process that sent you the
* current transaction that is being processed. This is the user
* of the caller. It is distinct from {@link #getCallingUid()} in that a
* particular user will have multiple distinct apps running under it each
* with their own uid. If the current thread is not currently executing an
* incoming transaction, then its own UserHandle is returned.
* 返回分配給發(fā)送給正在處理的當(dāng)前事務(wù)的進(jìn)程的UserHandle辩恼。 這是
* 呼叫者的用戶雇庙。 與getCallingUid()不同,特定用戶將具有多個(gè)不同的
* 應(yīng)用程序灶伊,每個(gè)應(yīng)用程序都具有自己的uid疆前。 如果當(dāng)前線程當(dāng)前沒有
* 執(zhí)行傳入事務(wù),則返回其自己的UserHandle聘萨。
*/
public static final UserHandle getCallingUserHandle() {
return UserHandle.of(UserHandle.getUserId(getCallingUid()));
}
/**
* Reset the identity of the incoming IPC on the current thread. This can
* be useful if, while handling an incoming call, you will be calling
* on interfaces of other objects that may be local to your process and
* need to do permission checks on the calls coming into them (so they
* will check the permission of your own local process, and not whatever
* process originally called you).
* 重置當(dāng)前線程的IPC的身份竹椒。 如果在處理來電時(shí),您將會(huì)調(diào)用
* 其他對象的接口米辐,這些對象可能在本地進(jìn)程中胸完,并且需要對其中的調(diào)
* 用進(jìn)行權(quán)限檢查(不管原來的進(jìn)程是如何調(diào)用你的,他們都將將檢查
* 您自己進(jìn)程的的訪問權(quán)限)翘贮。
* //最后一句話我實(shí)在是翻譯不好
* @return Returns an opaque token that can be used to restore the
* original calling identity by passing it to
* {@link #restoreCallingIdentity(long)}.
*
* 返回一個(gè)不透明的token赊窥,通過restoreCallingIdentity(long)這個(gè)方法
* 可以恢復(fù)原始呼叫的身份標(biāo)識
* @see #getCallingPid()
* @see #getCallingUid()
* @see #restoreCallingIdentity(long)
*/
public static final native long clearCallingIdentity();
/**
* Restore the identity of the incoming IPC on the current thread
* back to a previously identity that was returned by {@link
* #clearCallingIdentity}.
* 恢復(fù)之前當(dāng)前線程上的傳入IPC的身份標(biāo)識薯鼠。這個(gè)身份標(biāo)識是由
* clearCallingIdentity()方法改變的
* @param token The opaque token that was previously returned by
* {@link #clearCallingIdentity}.
* token 參數(shù)是 以前由{@link #clearCallingIdentity}返回的 tocken
*
* @see #clearCallingIdentity
*/
public static final native void restoreCallingIdentity(long token);
/**
* Sets the native thread-local StrictMode policy mask.
* 設(shè)置 native層線程的StrictMode策略掩碼乞而。
* <p>The StrictMode settings are kept in two places: a Java-level
* threadlocal for libcore/Dalvik, and a native threadlocal (set
* here) for propagation via Binder calls. This is a little
* unfortunate, but necessary to break otherwise more unfortunate
* dependencies either of Dalvik on Android, or Android
* native-only code on Dalvik.
*
* StrictMode設(shè)置保存在兩個(gè)地方:Java級別的 本地線程 在libcore / Dalvik中進(jìn)行設(shè)置,
* 和 native的 本地線程則通過Binder調(diào)用來設(shè)置离熏。 這有點(diǎn)兒不幸芍耘,但總
* 比依賴于Android上的Dalvik或者Android上Dalvik的native-only代碼要好
* @see StrictMode
* @hide
*/
public static final native void setThreadStrictModePolicy(int policyMask);
/**
* Gets the current native thread-local StrictMode policy mask.
* 獲取當(dāng)前native 的StrictMode策略掩碼
* @see #setThreadStrictModePolicy
* @hide
*/
public static final native int getThreadStrictModePolicy();
/**
* Flush any Binder commands pending in the current thread to the kernel
* driver. This can be
* useful to call before performing an operation that may block for a long
* time, to ensure that any pending object references have been released
* in order to prevent the process from holding on to objects longer than
* it needs to.
* 將當(dāng)前線程中的Binder命令刷新到內(nèi)核驅(qū)動(dòng)程序中址遇。這在執(zhí)行可能會(huì)
* 長時(shí)間阻塞的操作之前調(diào)用是有用的,因?yàn)檫@樣可以確保已經(jīng)釋放了
* 任何掛起的對象引用斋竞,以防止進(jìn)程持續(xù)到比需要的對象更長的時(shí)間倔约。
*/
public static final native void flushPendingCommands();
/**
* Add the calling thread to the IPC thread pool. This function does
* not return until the current process is exiting.
* 將調(diào)用線程添加到IPC線程池。 此方法在當(dāng)前進(jìn)程退出之前不返回窃页。
*/
public static final native void joinThreadPool();
/**
* Returns true if the specified interface is a proxy.
* 如果指定的接口是代理,則返回true复濒。
* @hide
*/
public static final boolean isProxy(IInterface iface) {
return iface.asBinder() != iface;
}
/**
* Call blocks until the number of executing binder threads is less
* than the maximum number of binder threads allowed for this process.
* 調(diào)用塊直到執(zhí)行綁定線程數(shù)量小于此進(jìn)程允許的綁定線程的最大數(shù)量脖卖。
* @hide
*/
public static final native void blockUntilThreadAvailable();
/**
* Default constructor initializes the object.
*/
public Binder() {
init();
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Binder> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
}
/**
* Convenience method for associating a specific interface with the Binder.
* After calling, queryLocalInterface() will be implemented for you
* to return the given owner IInterface when the corresponding
* descriptor is requested.
*/
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
/**
* Default implementation returns an empty interface name.
*/
public String getInterfaceDescriptor() {
return mDescriptor;
}
/**
* Default implementation always returns true -- if you got here,
* the object is alive.
*/
public boolean pingBinder() {
return true;
}
/**
* {@inheritDoc}
*
* Note that if you're calling on a local binder, this always returns true
* because your process is alive if you're calling it.
*/
public boolean isBinderAlive() {
return true;
}
/**
* Use information supplied to attachInterface() to return the
* associated IInterface if it matches the requested
* descriptor.
*/
public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
/**
* Control disabling of dump calls in this process. This is used by the system
* process watchdog to disable incoming dump calls while it has detecting the system
* is hung and is reporting that back to the activity controller. This is to
* prevent the controller from getting hung up on bug reports at this point.
* @hide
*
* @param msg The message to show instead of the dump; if null, dumps are
* re-enabled.
*/
public static void setDumpDisabled(String msg) {
synchronized (Binder.class) {
sDumpDisabled = msg;
}
}
/**
* Default implementation is a stub that returns false. You will want
* to override this to do the appropriate unmarshalling of transactions.
*
* <p>If you want to call this, call transact().
*/
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (code == INTERFACE_TRANSACTION) {
reply.writeString(getInterfaceDescriptor());
return true;
} else if (code == DUMP_TRANSACTION) {
ParcelFileDescriptor fd = data.readFileDescriptor();
String[] args = data.readStringArray();
if (fd != null) {
try {
dump(fd.getFileDescriptor(), args);
} finally {
IoUtils.closeQuietly(fd);
}
}
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
return true;
} else if (code == SHELL_COMMAND_TRANSACTION) {
ParcelFileDescriptor in = data.readFileDescriptor();
ParcelFileDescriptor out = data.readFileDescriptor();
ParcelFileDescriptor err = data.readFileDescriptor();
String[] args = data.readStringArray();
ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
try {
if (out != null) {
shellCommand(in != null ? in.getFileDescriptor() : null,
out.getFileDescriptor(),
err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
args, resultReceiver);
}
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(err);
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
}
return true;
}
return false;
}
/**
* Implemented to call the more convenient version
* {@link #dump(FileDescriptor, PrintWriter, String[])}.
*/
public void dump(FileDescriptor fd, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
try {
doDump(fd, pw, args);
} finally {
pw.flush();
}
}
void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
final String disabled;
synchronized (Binder.class) {
disabled = sDumpDisabled;
}
if (disabled == null) {
try {
dump(fd, pw, args);
} catch (SecurityException e) {
pw.println("Security exception: " + e.getMessage());
throw e;
} catch (Throwable e) {
// Unlike usual calls, in this case if an exception gets thrown
// back to us we want to print it back in to the dump data, since
// that is where the caller expects all interesting information to
// go.
pw.println();
pw.println("Exception occurred while dumping:");
e.printStackTrace(pw);
}
} else {
pw.println(sDumpDisabled);
}
}
/**
* Like {@link #dump(FileDescriptor, String[])}, but ensures the target
* executes asynchronously.
*/
public void dumpAsync(final FileDescriptor fd, final String[] args) {
final FileOutputStream fout = new FileOutputStream(fd);
final PrintWriter pw = new FastPrintWriter(fout);
Thread thr = new Thread("Binder.dumpAsync") {
public void run() {
try {
dump(fd, pw, args);
} finally {
pw.flush();
}
}
};
thr.start();
}
/**
* Print the object's state into the given stream.
*
* @param fd The raw file descriptor that the dump is being sent to.
* @param fout The file to which you should dump your state. This will be
* closed for you after you return.
* @param args additional arguments to the dump request.
*/
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
}
/**
* @param in The raw file descriptor that an input data stream can be read from.
* @param out The raw file descriptor that normal command messages should be written to.
* @param err The raw file descriptor that command error messages should be written to.
* @param args Command-line arguments.
* @param resultReceiver Called when the command has finished executing, with the result code.
* @throws RemoteException
* @hide
*/
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ResultReceiver resultReceiver) throws RemoteException {
onShellCommand(in, out, err, args, resultReceiver);
}
/**
* Handle a call to {@link #shellCommand}. The default implementation simply prints
* an error message. Override and replace with your own.
* <p class="caution">Note: no permission checking is done before calling this method; you must
* apply any security checks as appropriate for the command being executed.
* Consider using {@link ShellCommand} to help in the implementation.</p>
* @hide
*/
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ResultReceiver resultReceiver) throws RemoteException {
FileOutputStream fout = new FileOutputStream(err != null ? err : out);
PrintWriter pw = new FastPrintWriter(fout);
pw.println("No shell command implementation.");
pw.flush();
resultReceiver.send(0, null);
}
/**
* Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
/**
* Local implementation is a no-op.
*/
public void linkToDeath(DeathRecipient recipient, int flags) {
}
/**
* Local implementation is a no-op.
*/
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return true;
}
protected void finalize() throws Throwable {
try {
destroy();
} finally {
super.finalize();
}
}
static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {
if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {
// Trying to send > 800k, this is way too much
StringBuilder sb = new StringBuilder();
sb.append(msg);
sb.append(": on ");
sb.append(obj);
sb.append(" calling ");
sb.append(code);
sb.append(" size ");
sb.append(parcel.dataSize());
sb.append(" (data: ");
parcel.setDataPosition(0);
sb.append(parcel.readInt());
sb.append(", ");
sb.append(parcel.readInt());
sb.append(", ");
sb.append(parcel.readInt());
sb.append(")");
Slog.wtfStack(TAG, sb.toString());
}
}
private native final void init();
private native final void destroy();
// Entry point from android_util_Binder.cpp's onTransact
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
// theoretically, we should call transact, which will call onTransact,
// but all that does is rewind it, and we just got these from an IPC,
// so we'll just call it directly.
boolean res;
// Log any exceptions as warnings, don't silently suppress them.
// If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
try {
res = onTransact(code, data, reply, flags);
} catch (RemoteException|RuntimeException e) {
if (LOG_RUNTIME_EXCEPTION) {
Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
}
if ((flags & FLAG_ONEWAY) != 0) {
if (e instanceof RemoteException) {
Log.w(TAG, "Binder call failed.", e);
} else {
Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
}
} else {
reply.setDataPosition(0);
reply.writeException(e);
}
res = true;
} catch (OutOfMemoryError e) {
// Unconditionally log this, since this is generally unrecoverable.
Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);
RuntimeException re = new RuntimeException("Out of memory", e);
reply.setDataPosition(0);
reply.writeException(re);
res = true;
}
checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
reply.recycle();
data.recycle();
// Just in case -- we are done with the IPC, so there should be no more strict
// mode violations that have gathered for this thread. Either they have been
// parceled and are now in transport off to the caller, or we are returning back
// to the main transaction loop to wait for another incoming transaction. Either
// way, strict mode begone!
StrictMode.clearGatheredViolations();
return res;
}
}
1、類注釋
- 遠(yuǎn)程對象的基類巧颈,由IBinder定義的輕量級遠(yuǎn)程調(diào)用機(jī)制的核心部分畦木。這個(gè)類是IBinder的實(shí)現(xiàn)類。它提供了這種對象的標(biāo)準(zhǔn)本地實(shí)現(xiàn)砸泛。
- 大多數(shù)開發(fā)人員不會(huì)直接使用這個(gè)類十籍,而是使用 AIDL工具來實(shí)現(xiàn)這個(gè)接口蛆封,使其生成適當(dāng)?shù)腂inder子類。 但是勾栗,您可以直接從Binder派生自己的自定義RPC協(xié)議惨篱,也可以直接實(shí)例化一個(gè)原始的Binder對象,把它當(dāng)做一個(gè)token围俘,來進(jìn)行跨進(jìn)程通信砸讳。
- 這個(gè)Binder類是一個(gè)基礎(chǔ)的IPC原生類,它對application的生命周期沒有影響的界牡,它僅當(dāng)創(chuàng)建它的進(jìn)程還活著的時(shí)候才有效簿寂。所以為了正確的使用它,你必須在一個(gè)頂級的app組件里明確地讓系統(tǒng)知道宿亡,
這個(gè)Binder類是一個(gè)基礎(chǔ)的IPC原生類常遂,它對applicant的生命周期沒有影響,它僅當(dāng)創(chuàng)建它的進(jìn)程還活著的時(shí)候才有效挽荠。所以為了正確地使用它克胳,你必須在一個(gè)頂級app組件(例如service、activity或者ContentProvider)里明確地讓系統(tǒng)知道坤按,您的進(jìn)程應(yīng)該保持運(yùn)行毯欣。- 你必須牢記你的進(jìn)程可能會(huì)消失的情況,如果發(fā)生了這種情況臭脓,你必須在進(jìn)程重啟的時(shí)候創(chuàng)建一個(gè)新的Binder酗钞,并且關(guān)聯(lián)這個(gè)進(jìn)程。例如来累,如果你在Activity里面使用了Binder砚作,你的Activity進(jìn)程可能會(huì)被殺死,過了一會(huì)后嘹锁,如果activity比重新啟動(dòng)了葫录,這時(shí)候你要重新創(chuàng)建的一個(gè)新的Binder,并且把這個(gè)心的Binder放回之前的位置领猾。你也要注意到是米同,你的進(jìn)程可能因?yàn)橐恍┰?比如接收broadcast)而啟動(dòng),在這種情況下摔竿,是不需要重新創(chuàng)建Activity的面粮,這時(shí)候就需要運(yùn)行其他的一些代碼去創(chuàng)建Binder對象。
2继低、關(guān)于Binder的構(gòu)造函數(shù)
Binder就提供一個(gè)默認(rèn)的構(gòu)造函數(shù),代碼如下
/**
* Default constructor initializes the object.
*/
public Binder() {
init();
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Binder> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
}
private native final void init();
- 首先是執(zhí)行init()方法熬苍,init()是native層的,這里就暫不跟蹤了。
- 判斷是否是匿名內(nèi)部類柴底,或者內(nèi)部類婿脸,如果是的話,打印日志柄驻。
通過上面我們知道Binder這個(gè)類的核心構(gòu)造函數(shù)是在native實(shí)現(xiàn)的狐树。
3、Binder的重要方法
(1)凿歼、attachInterface(IInterface, String)方法
/**
* Convenience method for associating a specific interface with the Binder.
* After calling, queryLocalInterface() will be implemented for you
* to return the given owner IInterface when the corresponding
* descriptor is requested.
* 將特定接口與Binder相關(guān)聯(lián)的快捷方法褪迟。 調(diào)用之后,將會(huì)實(shí)現(xiàn)
* queryLocalInterface(), 當(dāng)你請求相應(yīng)的描述符時(shí)答憔,queryLocalInterface()
* 將返回給定的所有者IInterface味赃。
*/
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
(2)、getInterfaceDescriptor()方法
/**
* Default implementation returns an empty interface name.
* 默認(rèn)實(shí)現(xiàn)返回一個(gè)空的接口名稱虐拓。
*/
public String getInterfaceDescriptor() {
return mDescriptor;
}
(3)心俗、pingBinder()方法
/**
* Default implementation always returns true -- if you got here,
* the object is alive.
* 默認(rèn)實(shí)現(xiàn)總是返回true - 如果你走到這里,對象是活著的蓉驹。
*/
public boolean pingBinder() {
return true;
}
(4)城榛、isBinderAlive()方法
/**
* {@inheritDoc}
*
* Note that if you're calling on a local binder, this always returns true
* because your process is alive if you're calling it.
* 請注意,如果您正在調(diào)用本地的Binder态兴,則始終返回true
* 如果你能調(diào)用他狠持,則你的進(jìn)程一定是活著的。
*/
public boolean isBinderAlive() {
return true;
}
(5)瞻润、queryLocalInterface(String)方法
/**
* Use information supplied to attachInterface() to return the
* associated IInterface if it matches the requested
* descriptor.
* 如果提供的描述符和之前關(guān)聯(lián)的IInterface(通過attachInterface()
* 方法進(jìn)行關(guān)聯(lián))的描述符一致喘垂,則返回相對應(yīng)的IInterface
*/
public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
(6)、setDumpDisabled(String)方法
/**
* Control disabling of dump calls in this process. This is used by the system
* process watchdog to disable incoming dump calls while it has detecting the system
* is hung and is reporting that back to the activity controller. This is to
* prevent the controller from getting hung up on bug reports at this point.
* @hide
*
* @param msg The message to show instead of the dump; if null, dumps are
* re-enabled.
*/
public static void setDumpDisabled(String msg) {
synchronized (Binder.class) {
sDumpDisabled = msg;
}
}
(二)绍撞、BinderProxy
final class BinderProxy implements IBinder {
public native boolean pingBinder();
public native boolean isBinderAlive();
public IInterface queryLocalInterface(String descriptor) {
return null;
}
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
return transactNative(code, data, reply, flags);
}
public native String getInterfaceDescriptor() throws RemoteException;
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
public native void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
public void dump(FileDescriptor fd, String[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeFileDescriptor(fd);
data.writeStringArray(args);
try {
transact(DUMP_TRANSACTION, data, reply, 0);
reply.readException();
} finally {
data.recycle();
reply.recycle();
}
}
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeFileDescriptor(fd);
data.writeStringArray(args);
try {
transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
} finally {
data.recycle();
reply.recycle();
}
}
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ResultReceiver resultReceiver) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeFileDescriptor(in);
data.writeFileDescriptor(out);
data.writeFileDescriptor(err);
data.writeStringArray(args);
resultReceiver.writeToParcel(data, 0);
try {
transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
reply.readException();
} finally {
data.recycle();
reply.recycle();
}
}
BinderProxy() {
mSelf = new WeakReference(this);
}
@Override
protected void finalize() throws Throwable {
try {
destroy();
} finally {
super.finalize();
}
}
private native final void destroy();
private static final void sendDeathNotice(DeathRecipient recipient) {
if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
try {
recipient.binderDied();
}
catch (RuntimeException exc) {
Log.w("BinderNative", "Uncaught exception from death notification",
exc);
}
}
final private WeakReference mSelf;
private long mObject;
private long mOrgue;
}
四正勒、總結(jié)
所以大體的結(jié)構(gòu)類圖圖下圖: