Android跨進程通信IPC整體內(nèi)容如下
- 1、Android跨進程通信IPC之1——Linux基礎(chǔ)
- 2、Android跨進程通信IPC之2——Bionic
- 3、Android跨進程通信IPC之3——關(guān)于"JNI"的那些事
- 4、Android跨進程通信IPC之4——AndroidIPC基礎(chǔ)1
- 4、Android跨進程通信IPC之4——AndroidIPC基礎(chǔ)2
- 5、Android跨進程通信IPC之5——Binder的三大接口
- 6、Android跨進程通信IPC之6——Binder框架
- 7、Android跨進程通信IPC之7——Binder相關(guān)結(jié)構(gòu)體簡介
- 8、Android跨進程通信IPC之8——Binder驅(qū)動
- 9、Android跨進程通信IPC之9——Binder之Framework層C++篇1
- 9、Android跨進程通信IPC之9——Binder之Framework層C++篇2
- 10、Android跨進程通信IPC之10——Binder之Framework層Java篇
- 11、Android跨進程通信IPC之11——AIDL
- 12、Android跨進程通信IPC之12——Binder補充
- 13、Android跨進程通信IPC之13——Binder總結(jié)
- 14、Android跨進程通信IPC之14——其他IPC方式
- 15、Android跨進程通信IPC之15——感謝
本片文章的主要目的是讓大家對Binder有個初步的了解,既然是初步了解,肯定所是以源碼上的注釋為主,讓大家對Binder有一個更直觀的認識。PS:大部分注釋我是寫在類里面了, 重要的我會單獨的拿出來。
主要內(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)接口的基類。 定義新接口的時候,你必須從IInterface派生。
(二)、抽象方法注釋
如果想獲取和該接口關(guān)聯(lián)的Binder對象。你必須使用這個方法來而不是使用一個簡單的類型轉(zhuǎn)化。這樣代理對象才能返回正確的結(jié)果
(三)、總結(jié)
所以可以這樣說IInterface接口提供了類型轉(zhuǎn)化的功能,將服務(wù)或者服務(wù)代理類轉(zhuǎn)為IBinder類型。其實實際的類型轉(zhuǎn)換是由BnInterface、BpInterface兩個類完成的,BnInterface將服務(wù)類轉(zhuǎn)換成IBinder類型,而BpInterface則將代理服務(wù)類轉(zhuǎn)換成IBinder類型。在通過Binder Driver傳遞Binder對象時,必須進行類型轉(zhuǎn)換,比如在想系統(tǒng)注冊服務(wù)時,需要先將服務(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.
* 第一個可用于用戶命令的事務(wù)代碼。
*/
int FIRST_CALL_TRANSACTION = 0x00000001;
/**
* The last transaction code available for user commands.
* 最后一個可用于用戶命令的事務(wù)代碼。
*/
int LAST_CALL_TRANSACTION = 0x00ffffff;
/**
* IBinder protocol transaction code: pingBinder().
* IBinder協(xié)議事物碼:在pingBinder()會用到
*/
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í)行一個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é)議事物碼:向目標對象發(fā)出一個呼叫。在parcel中的數(shù)據(jù)是用于
* 分發(fā)一個與對象結(jié)合的共享信息服務(wù)。它可以是任何東西,只要它不超
* 過130個UTF-8字符,保證適用于常見的信息服務(wù)。 作為
* Build.VERSION_CODES#HONEYCOMB_MR2的一部分,所有的binder
* 對象都支持這個協(xié)議,為了在跨平臺間完整推送同時也為了支持舊的交
* 互碼,一個默認的實現(xiàn)是在主日志中記錄了一個推送,作為廣播的一個
* 簡單模仿。
* 并且,為了完成消息的派送,對象必須返回給調(diào)用者一個說明,
* 表明是舊的信息。
*/
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 有一個調(diào)用者在呼叫它。這個app負
* 責計算和維護自己的呼叫者數(shù)目。 并且可以展示這個值來告訴用戶app
* 的狀態(tài)。這個是可選的命令,app不需要掌管它,所以默認是實現(xiàn)是什
* 么都不做。
* 這是沒有響應(yīng)的,并且不會對系統(tǒng)帶來影響,但是它提高了app的自控
* (我真的不知道怎么翻譯,elf-esteem其實是自尊的意思)
*/
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,表明呼叫者會馬上返回,
* 不必等結(jié)果從被呼叫者返回。只有當呼叫者和被呼叫者在不同的進程中
* 才有效.
*/
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.
* 獲取一個支持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,主機進程消失,否則結(jié)果為true(始終默認true)由對
* 手方來實現(xiàn)pingBinder()這個方法。
*/
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所在的進程是否仍然存在
* 如果進程不存在,則返回false。 請注意,如果返回true,則調(diào)用返回時
* 進程可能已經(jīng)死機。
*/
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);
}
注釋有點多,我們一個一個來
(一)、類注釋
簡單的翻譯一下:
- 一個遠程對象的基接口,是為高性能而設(shè)計的輕量級遠程調(diào)用機制的核心部分,它不僅用于遠程調(diào)用,也可以用于進程內(nèi)調(diào)用。這個接口描述了與遠程對象進行交互的抽象協(xié)議。建議繼承Binder類,而不是直接實現(xiàn)這個接口。
IBinder的主要API是transact(),與它對應(yīng)另一個方法是Binder.onTransact。第一個方法使你可以向遠端的IBinder對象發(fā)送調(diào)用,第二個方法使你自己的遠程對象能夠響應(yīng)接收到的調(diào)用。IBinder的API都是同步執(zhí)行的,比如transact()直到對方的Binder.onTransact()方法調(diào)用完成后才返回。而在跨進程的時候,在IPC的幫助下,也是同樣的效果。
通過transact()發(fā)送的數(shù)據(jù)是Parcel,Parcel是一種一般的緩沖區(qū),除了有數(shù)據(jù)外還帶有一些描述它內(nèi)容的元數(shù)據(jù)。元數(shù)據(jù)用于管理IBinder對象的引用,這樣就能在緩沖去從一個進程移動到另一個進程時,保存這些引用。這樣就保證了當一個IBinder被寫入到Parcel并發(fā)送到另一個進程中,如果另一個進程把同一個IBinder的引用回發(fā)到原來的進程,那么這個原來的進程就能接收到發(fā)出的那個IBinder的引用。這種機制使IBinder和Binder像唯一標志符那樣在進程間管理。
系統(tǒng)為每一個進程維持一個存放交互的線程池。這些交互的線程用于派發(fā)所有從其他進程發(fā)來的IPC調(diào)用。例如:當一個IPC從進程A發(fā)到進程B,A中那個發(fā)出調(diào)用的線程就阻塞在transact()中了。進程B中的交互線程池的一個線程池接收了這個調(diào)用,它調(diào)用Binder.onTransact(),完成后用一個Parcel來作為結(jié)果返回。然后進程A中的那個等待線程在收到返回的Parcel才能繼續(xù)執(zhí)行。實際上,另一個進程看起來就像當前進程的一個線程,但不是當前進程創(chuàng)建的。
Binder機制還支持進程間的遞歸調(diào)用。例如,進程A執(zhí)行自己的IBinder的transact()調(diào)用進程B的Binder,而進程B在其Binder.onTransact()中又用transact()向進程A發(fā)起調(diào)用,那么進程A在等待它發(fā)布出的調(diào)用返回的同時,還會用Binder.onTransact()響應(yīng)進程B的transact()。總之,Binder造成的結(jié)果就是讓我們感覺到跨進程的調(diào)用與進程內(nèi)的調(diào)用沒有什么區(qū)別。
當操作遠程對象的時候,你需要經(jīng)常查看它們是否有效,有3種方法可以使用:
- 1 transact()方法將在IBinder所在的進程不存在時拋出RemoteException異常
- 2 如果目標進程不存在,那么調(diào)用pingBinder()時返回false\
- 3 可以用linkToDeath()方法向IBinder注冊一個IBinder.DeathRecipient,在IBinder代表的進程退出時被調(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);
翻譯如下:
用于接收一個用于當前binder對象的本地接口的實現(xiàn)。如果返回null,你需要通過transact()方法去實例化一個代理類。
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)儲發(fā)送到的原始文件描述符。
- 入?yún)rgs: 轉(zhuǎn)儲請求的附加參數(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í)行。如果對象在本地, 一個新的線程將會被創(chuàng)建去執(zhí)行這個操作。
- 入?yún)d:轉(zhuǎn)儲發(fā)送到的原始文件描述符。
- 入?yún)rgs: 轉(zhuǎn)儲請求的附加參數(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:命令錯誤消息應(yīng)寫入的原始文件描述符。
- 入?yún)rgs: 命令行參數(shù)。
- 入?yún)esultReceiver: 當命令執(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í)行一個通用的操作
- 入?yún)ode:操作碼必須在FIRST_CALL_TRANSACTION和LAST_CALL_TRANSACTION之間
- 入?yún)ata: 傳輸給目標的數(shù)據(jù)。如果你沒有傳輸任何數(shù)據(jù),你必須創(chuàng)建一個空的Parcel
- 入?yún)eply:從目標接收的數(shù)據(jù)。可以是null如果你對返回的值不感興趣。
- 入?yún)lags: 附加操作標志。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;
翻譯如下:
注冊一個recipient用于提示binder消失。如果binder對象異常地消失(例如由于主進程被殺),DeathRecipient中的binderDied會被調(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不再會被調(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();
}
翻譯如下:
當持有IBinder進程消失,會回調(diào)這個接口
(四)、總結(jié):
通過上面對IBinder注釋,我們大概可以知道以下信息
- 1、IBindre是遠程對象的基接口,不僅可以在跨進程可以調(diào)用,也可以在進程內(nèi)部調(diào)用
- 2、在遠程調(diào)用的時候,一端用IBinder.transact()發(fā)送,另一端用Binder的Binder.onTransact()接受,并且是同步的
- 3、transact()方法發(fā)送的是Parcel。
- 4、系統(tǒng)為每個進程維護一個進行跨進程調(diào)用的線程池。
- 5、可以使用pingBinder()方法來檢測目標進程是否存在
- 6、可以調(diào)用linkToDeath()來向IBinder注冊一個IBinder.DeathRecipien。用于目標進程退出時候的提醒。
- 7、建議繼承Binder類,而不是直接實現(xiàn)這個接口。
三、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è)置這個標記來檢測是否是Binder的匿名內(nèi)部類,或者Binder的
* 本地內(nèi)部類,因為這些類可能會存在潛在的內(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.
* 進程的全局事務(wù)跟蹤器實例。
*/
private static TransactionTracker sTransactionTracker = null;
// Transaction tracking code.
// 事務(wù)跟蹤代碼
/**
* Flag indicating whether we should be tracing transact calls.
* 標志, 表示我們是否應(yīng)該跟蹤事務(wù)調(diào)用。
*/
private static boolean sTracingEnabled = false;
/**
* Enable Binder IPC tracing.
* 啟動 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.
* 獲取此進程的 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 會被Native 代碼調(diào)用,不要刪除或重命名
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ā)送正在處理的當前事務(wù)的進程的ID。 該pid可以與更高級
* 別的系統(tǒng)服務(wù)一起使用,以確定其身份和檢查權(quán)限。 如果當前線程當
* 前沒有執(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ā)送正在處理的當前事務(wù)的進程。
* 這個uid可以與更高級別的系統(tǒng)服務(wù)一起使用,以確定其身份和檢查
* 權(quán)限。 如果當前線程當前沒有執(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ā)送給正在處理的當前事務(wù)的進程的UserHandle。 這是
* 呼叫者的用戶。 與getCallingUid()不同,特定用戶將具有多個不同的
* 應(yīng)用程序,每個應(yīng)用程序都具有自己的uid。 如果當前線程當前沒有
* 執(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).
* 重置當前線程的IPC的身份。 如果在處理來電時,您將會調(diào)用
* 其他對象的接口,這些對象可能在本地進程中,并且需要對其中的調(diào)
* 用進行權(quán)限檢查(不管原來的進程是如何調(diào)用你的,他們都將將檢查
* 您自己進程的的訪問權(quán)限)。
* //最后一句話我實在是翻譯不好
* @return Returns an opaque token that can be used to restore the
* original calling identity by passing it to
* {@link #restoreCallingIdentity(long)}.
*
* 返回一個不透明的token,通過restoreCallingIdentity(long)這個方法
* 可以恢復(fù)原始呼叫的身份標識
* @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ù)之前當前線程上的傳入IPC的身份標識。這個身份標識是由
* 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è)置保存在兩個地方:Java級別的 本地線程 在libcore / Dalvik中進行設(shè)置,
* 和 native的 本地線程則通過Binder調(diào)用來設(shè)置。 這有點兒不幸,但總
* 比依賴于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.
* 獲取當前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.
* 將當前線程中的Binder命令刷新到內(nèi)核驅(qū)動程序中。這在執(zhí)行可能會
* 長時間阻塞的操作之前調(diào)用是有用的,因為這樣可以確保已經(jīng)釋放了
* 任何掛起的對象引用,以防止進程持續(xù)到比需要的對象更長的時間。
*/
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線程池。 此方法在當前進程退出之前不返回。
*/
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ù)量小于此進程允許的綁定線程的最大數(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、類注釋
- 遠程對象的基類,由IBinder定義的輕量級遠程調(diào)用機制的核心部分。這個類是IBinder的實現(xiàn)類。它提供了這種對象的標準本地實現(xiàn)。
- 大多數(shù)開發(fā)人員不會直接使用這個類,而是使用 AIDL工具來實現(xiàn)這個接口,使其生成適當?shù)腂inder子類。 但是,您可以直接從Binder派生自己的自定義RPC協(xié)議,也可以直接實例化一個原始的Binder對象,把它當做一個token,來進行跨進程通信。
- 這個Binder類是一個基礎(chǔ)的IPC原生類,它對application的生命周期沒有影響的,它僅當創(chuàng)建它的進程還活著的時候才有效。所以為了正確的使用它,你必須在一個頂級的app組件里明確地讓系統(tǒng)知道,
這個Binder類是一個基礎(chǔ)的IPC原生類,它對applicant的生命周期沒有影響,它僅當創(chuàng)建它的進程還活著的時候才有效。所以為了正確地使用它,你必須在一個頂級app組件(例如service、activity或者ContentProvider)里明確地讓系統(tǒng)知道,您的進程應(yīng)該保持運行。- 你必須牢記你的進程可能會消失的情況,如果發(fā)生了這種情況,你必須在進程重啟的時候創(chuàng)建一個新的Binder,并且關(guān)聯(lián)這個進程。例如,如果你在Activity里面使用了Binder,你的Activity進程可能會被殺死,過了一會后,如果activity比重新啟動了,這時候你要重新創(chuàng)建的一個新的Binder,并且把這個心的Binder放回之前的位置。你也要注意到是,你的進程可能因為一些原因(比如接收broadcast)而啟動,在這種情況下,是不需要重新創(chuàng)建Activity的,這時候就需要運行其他的一些代碼去創(chuàng)建Binder對象。
2、關(guān)于Binder的構(gòu)造函數(shù)
Binder就提供一個默認的構(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òu)造函數(shù)是在native實現(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)用之后,將會實現(xiàn)
* queryLocalInterface(), 當你請求相應(yīng)的描述符時,queryLocalInterface()
* 將返回給定的所有者IInterface。
*/
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
(2)、getInterfaceDescriptor()方法
/**
* Default implementation returns an empty interface name.
* 默認實現(xiàn)返回一個空的接口名稱。
*/
public String getInterfaceDescriptor() {
return mDescriptor;
}
(3)、pingBinder()方法
/**
* Default implementation always returns true -- if you got here,
* the object is alive.
* 默認實現(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)用他,則你的進程一定是活著的。
*/
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()
* 方法進行關(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)類圖圖下圖: