当前位置: 代码迷 >> Android >> Android学习日志(1)
  详细解决方案

Android学习日志(1)

热度:64   发布时间:2016-05-01 13:17:30.0
Android学习日记(1)

直接上代码:

IBinder类:

/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.os;import java.io.FileDescriptor;import java.io.PrintWriter;/** * 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 [email protected] Binder}. *  * <p>The key IBinder API is [email protected] #transact transact()} matched by * [email protected] 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 [email protected] #transact transact()} does not * return until the target has returned from * [email protected] 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 [email protected] 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 [email protected] #transact transact()} method will throw a * [email protected] RemoteException} exception if you try to call it on an IBinder * whose process no longer exists. * <li> The [email protected] #pingBinder()} method can be called, and will return false * if the remote process no longer exists. * <li> The [email protected] #linkToDeath linkToDeath()} method can be used to register * a [email protected] 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.     */    int FIRST_CALL_TRANSACTION  = 0x00000001;    /**     * The last transaction code available for user commands.     */    int LAST_CALL_TRANSACTION   = 0x00ffffff;        /**     * IBinder protocol transaction code: pingBinder().     */    int PING_TRANSACTION        = ('_'<<24)|('P'<<16)|('N'<<8)|'G';        /**     * IBinder protocol transaction code: dump internal state.     */    int DUMP_TRANSACTION        = ('_'<<24)|('D'<<16)|('M'<<8)|'P';        /**     * IBinder protocol transaction code: interrogate the recipient side     * of the transaction for its canonical interface descriptor.     */    int INTERFACE_TRANSACTION   = ('_'<<24)|('N'<<16)|('T'<<8)|'F';    /**     * Flag to [email protected] #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.     */    int FLAG_ONEWAY             = 0x00000001;        /**     * Get the canonical name of the interface supported by this binder.     */    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.     */    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.     */    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;        /**     * Perform a generic operation with the object.     *      * @param code The action to perform.  This should     * be a number between [email protected] #FIRST_CALL_TRANSACTION} and     * [email protected] #LAST_CALL_TRANSACTION}.     * @param data Marshalled data to send to the target.  Most 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 [email protected] #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 [email protected] DeathRecipient}'s     * [email protected] 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 Throws [email protected] 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 Returns true if the <var>recipient</var> is successfully     * unlinked, assuring you that its     * [email protected] DeathRecipient#binderDied DeathRecipient.binderDied()} method     * will not be called.  Returns false if the target IBinder has already     * died, meaning the method has been (or soon will be) called.     *      * @throws Throws [email protected] 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);}

?Binder类

?

/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.os;import android.util.Config;import android.util.Log;import java.io.FileDescriptor;import java.io.FileOutputStream;import java.io.IOException;import java.io.PrintWriter;import java.lang.ref.WeakReference;import java.lang.reflect.Modifier;/** * Base class for a remotable object, the core part of a lightweight * remote procedure call mechanism defined by [email protected] IBinder}. * This class is an implementation of IBinder that provides * the standard support creating a local implementation of such an object. *  * <p>Most developers will not implement this class directly, instead using the * <a href="[email protected]}guide/developing/tools/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. *  * @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.     */    private static final boolean FIND_POTENTIAL_LEAKS = false;    private static final String TAG = "Binder";    private int 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.     */    public static final native int getCallingPid();        /**     * Return the ID of the user 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.     */    public static final native int 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).     *     * @return Returns an opaque token that can be used to restore the     * original calling identity by passing it to     * [email protected] #restoreCallingIdentity(long)}.     *     * @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 [email protected]     * #clearCallingIdentity}.     *     * @param token The opaque token that was previously returned by     * [email protected] #clearCallingIdentity}.     *     * @see #clearCallingIdentity     */    public static final native void restoreCallingIdentity(long token);        /**     * 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.     */    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.     */    public static final native void joinThreadPool();        /**     * 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;    }    /**     * [email protected]}     *     * 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;    }        /**     * 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 {                    try {                        fd.close();                    } catch (IOException e) {                    }                }            }            return true;        }        return false;    }    /**     * Implemented to call the more convenient version     * [email protected] #dump(FileDescriptor, PrintWriter, String[])}.     */    public void dump(FileDescriptor fd, String[] args) {        FileOutputStream fout = new FileOutputStream(fd);        PrintWriter pw = new PrintWriter(fout);        try {            dump(fd, pw, args);        } finally {            pw.flush();        }    }        /**     * 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) {    }    /**     * 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 (Config.LOGV) 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();        }    }        private native final void init();    private native final void destroy();    private boolean execTransact(int code, int dataObj, int 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;        try {            res = onTransact(code, data, reply, flags);        } catch (RemoteException e) {            reply.writeException(e);            res = true;        } catch (RuntimeException e) {            reply.writeException(e);            res = true;        } catch (OutOfMemoryError e) {            RuntimeException re = new RuntimeException("Out of memory", e);            reply.writeException(re);            res = true;        }        reply.recycle();        data.recycle();        return res;    }}final class BinderProxy implements IBinder {    public native boolean pingBinder();    public native boolean isBinderAlive();        public IInterface queryLocalInterface(String descriptor) {        return null;    }        public native String getInterfaceDescriptor() throws RemoteException;    public native boolean transact(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();        data.writeFileDescriptor(fd);        data.writeStringArray(args);        try {            transact(DUMP_TRANSACTION, data, null, 0);        } finally {            data.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 (Config.LOGV) 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 int mObject;}
?
  相关解决方案