您的位置:首页 > 移动开发 > Android开发

Android学习日记(1)

2017-08-07 10:20 267 查看
直接上代码:

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 {@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.
*/
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 {@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.
*/
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 {@link #FIRST_CALL_TRANSACTION} and
* {@link #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 {@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 Throws {@link 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
* {@link 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 {@link 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 KIN
1276f
D, 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 {@link 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="{@docRoot}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
* {@link #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 {@link
* #clearCallingIdentity}.
*
* @param token The opaque token that was previously returned by
* {@link #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;
}

/**
* {@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;
}

/**
* 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
* {@link #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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: