diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:31:44 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:31:44 -0800 |
commit | 9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch) | |
tree | d88beb88001f2482911e3d28e43833b50e4b4e97 /core/java/android/os/Binder.java | |
parent | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff) | |
download | frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.zip frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.gz frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/os/Binder.java')
-rw-r--r-- | core/java/android/os/Binder.java | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java new file mode 100644 index 0000000..df10c6a --- /dev/null +++ b/core/java/android/os/Binder.java @@ -0,0 +1,355 @@ +/* + * 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 {@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 to the local process. 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 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; + } + 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; +} |