Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os;
     18 
     19 import android.util.Log;
     20 import com.android.internal.util.FastPrintWriter;
     21 
     22 import java.io.FileDescriptor;
     23 import java.io.FileOutputStream;
     24 import java.io.IOException;
     25 import java.io.PrintWriter;
     26 import java.lang.ref.WeakReference;
     27 import java.lang.reflect.Modifier;
     28 
     29 /**
     30  * Base class for a remotable object, the core part of a lightweight
     31  * remote procedure call mechanism defined by {@link IBinder}.
     32  * This class is an implementation of IBinder that provides
     33  * the standard support creating a local implementation of such an object.
     34  *
     35  * <p>Most developers will not implement this class directly, instead using the
     36  * <a href="{@docRoot}guide/components/aidl.html">aidl</a> tool to describe the desired
     37  * interface, having it generate the appropriate Binder subclass.  You can,
     38  * however, derive directly from Binder to implement your own custom RPC
     39  * protocol or simply instantiate a raw Binder object directly to use as a
     40  * token that can be shared across processes.
     41  *
     42  * @see IBinder
     43  */
     44 public class Binder implements IBinder {
     45     /*
     46      * Set this flag to true to detect anonymous, local or member classes
     47      * that extend this Binder class and that are not static. These kind
     48      * of classes can potentially create leaks.
     49      */
     50     private static final boolean FIND_POTENTIAL_LEAKS = false;
     51     private static final String TAG = "Binder";
     52 
     53     /**
     54      * Control whether dump() calls are allowed.
     55      */
     56     private static String sDumpDisabled = null;
     57 
     58     /* mObject is used by native code, do not remove or rename */
     59     private int mObject;
     60     private IInterface mOwner;
     61     private String mDescriptor;
     62 
     63     /**
     64      * Return the ID of the process that sent you the current transaction
     65      * that is being processed.  This pid can be used with higher-level
     66      * system services to determine its identity and check permissions.
     67      * If the current thread is not currently executing an incoming transaction,
     68      * then its own pid is returned.
     69      */
     70     public static final native int getCallingPid();
     71 
     72     /**
     73      * Return the Linux uid assigned to the process that sent you the
     74      * current transaction that is being processed.  This uid can be used with
     75      * higher-level system services to determine its identity and check
     76      * permissions.  If the current thread is not currently executing an
     77      * incoming transaction, then its own uid is returned.
     78      */
     79     public static final native int getCallingUid();
     80 
     81     /**
     82      * Return the UserHandle assigned to the process that sent you the
     83      * current transaction that is being processed.  This is the user
     84      * of the caller.  It is distinct from {@link #getCallingUid()} in that a
     85      * particular user will have multiple distinct apps running under it each
     86      * with their own uid.  If the current thread is not currently executing an
     87      * incoming transaction, then its own UserHandle is returned.
     88      */
     89     public static final UserHandle getCallingUserHandle() {
     90         return new UserHandle(UserHandle.getUserId(getCallingUid()));
     91     }
     92 
     93     /**
     94      * Reset the identity of the incoming IPC on the current thread.  This can
     95      * be useful if, while handling an incoming call, you will be calling
     96      * on interfaces of other objects that may be local to your process and
     97      * need to do permission checks on the calls coming into them (so they
     98      * will check the permission of your own local process, and not whatever
     99      * process originally called you).
    100      *
    101      * @return Returns an opaque token that can be used to restore the
    102      * original calling identity by passing it to
    103      * {@link #restoreCallingIdentity(long)}.
    104      *
    105      * @see #getCallingPid()
    106      * @see #getCallingUid()
    107      * @see #restoreCallingIdentity(long)
    108      */
    109     public static final native long clearCallingIdentity();
    110 
    111     /**
    112      * Restore the identity of the incoming IPC on the current thread
    113      * back to a previously identity that was returned by {@link
    114      * #clearCallingIdentity}.
    115      *
    116      * @param token The opaque token that was previously returned by
    117      * {@link #clearCallingIdentity}.
    118      *
    119      * @see #clearCallingIdentity
    120      */
    121     public static final native void restoreCallingIdentity(long token);
    122 
    123     /**
    124      * Sets the native thread-local StrictMode policy mask.
    125      *
    126      * <p>The StrictMode settings are kept in two places: a Java-level
    127      * threadlocal for libcore/Dalvik, and a native threadlocal (set
    128      * here) for propagation via Binder calls.  This is a little
    129      * unfortunate, but necessary to break otherwise more unfortunate
    130      * dependencies either of Dalvik on Android, or Android
    131      * native-only code on Dalvik.
    132      *
    133      * @see StrictMode
    134      * @hide
    135      */
    136     public static final native void setThreadStrictModePolicy(int policyMask);
    137 
    138     /**
    139      * Gets the current native thread-local StrictMode policy mask.
    140      *
    141      * @see #setThreadStrictModePolicy
    142      * @hide
    143      */
    144     public static final native int getThreadStrictModePolicy();
    145 
    146     /**
    147      * Flush any Binder commands pending in the current thread to the kernel
    148      * driver.  This can be
    149      * useful to call before performing an operation that may block for a long
    150      * time, to ensure that any pending object references have been released
    151      * in order to prevent the process from holding on to objects longer than
    152      * it needs to.
    153      */
    154     public static final native void flushPendingCommands();
    155 
    156     /**
    157      * Add the calling thread to the IPC thread pool.  This function does
    158      * not return until the current process is exiting.
    159      */
    160     public static final native void joinThreadPool();
    161 
    162     /**
    163      * Returns true if the specified interface is a proxy.
    164      * @hide
    165      */
    166     public static final boolean isProxy(IInterface iface) {
    167         return iface.asBinder() != iface;
    168     }
    169 
    170     /**
    171      * Default constructor initializes the object.
    172      */
    173     public Binder() {
    174         init();
    175 
    176         if (FIND_POTENTIAL_LEAKS) {
    177             final Class<? extends Binder> klass = getClass();
    178             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
    179                     (klass.getModifiers() & Modifier.STATIC) == 0) {
    180                 Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
    181                     klass.getCanonicalName());
    182             }
    183         }
    184     }
    185 
    186     /**
    187      * Convenience method for associating a specific interface with the Binder.
    188      * After calling, queryLocalInterface() will be implemented for you
    189      * to return the given owner IInterface when the corresponding
    190      * descriptor is requested.
    191      */
    192     public void attachInterface(IInterface owner, String descriptor) {
    193         mOwner = owner;
    194         mDescriptor = descriptor;
    195     }
    196 
    197     /**
    198      * Default implementation returns an empty interface name.
    199      */
    200     public String getInterfaceDescriptor() {
    201         return mDescriptor;
    202     }
    203 
    204     /**
    205      * Default implementation always returns true -- if you got here,
    206      * the object is alive.
    207      */
    208     public boolean pingBinder() {
    209         return true;
    210     }
    211 
    212     /**
    213      * {@inheritDoc}
    214      *
    215      * Note that if you're calling on a local binder, this always returns true
    216      * because your process is alive if you're calling it.
    217      */
    218     public boolean isBinderAlive() {
    219         return true;
    220     }
    221 
    222     /**
    223      * Use information supplied to attachInterface() to return the
    224      * associated IInterface if it matches the requested
    225      * descriptor.
    226      */
    227     public IInterface queryLocalInterface(String descriptor) {
    228         if (mDescriptor.equals(descriptor)) {
    229             return mOwner;
    230         }
    231         return null;
    232     }
    233 
    234     /**
    235      * Control disabling of dump calls in this process.  This is used by the system
    236      * process watchdog to disable incoming dump calls while it has detecting the system
    237      * is hung and is reporting that back to the activity controller.  This is to
    238      * prevent the controller from getting hung up on bug reports at this point.
    239      * @hide
    240      *
    241      * @param msg The message to show instead of the dump; if null, dumps are
    242      * re-enabled.
    243      */
    244     public static void setDumpDisabled(String msg) {
    245         synchronized (Binder.class) {
    246             sDumpDisabled = msg;
    247         }
    248     }
    249 
    250     /**
    251      * Default implementation is a stub that returns false.  You will want
    252      * to override this to do the appropriate unmarshalling of transactions.
    253      *
    254      * <p>If you want to call this, call transact().
    255      */
    256     protected boolean onTransact(int code, Parcel data, Parcel reply,
    257             int flags) throws RemoteException {
    258         if (code == INTERFACE_TRANSACTION) {
    259             reply.writeString(getInterfaceDescriptor());
    260             return true;
    261         } else if (code == DUMP_TRANSACTION) {
    262             ParcelFileDescriptor fd = data.readFileDescriptor();
    263             String[] args = data.readStringArray();
    264             if (fd != null) {
    265                 try {
    266                     dump(fd.getFileDescriptor(), args);
    267                 } finally {
    268                     try {
    269                         fd.close();
    270                     } catch (IOException e) {
    271                         // swallowed, not propagated back to the caller
    272                     }
    273                 }
    274             }
    275             // Write the StrictMode header.
    276             if (reply != null) {
    277                 reply.writeNoException();
    278             } else {
    279                 StrictMode.clearGatheredViolations();
    280             }
    281             return true;
    282         }
    283         return false;
    284     }
    285 
    286     /**
    287      * Implemented to call the more convenient version
    288      * {@link #dump(FileDescriptor, PrintWriter, String[])}.
    289      */
    290     public void dump(FileDescriptor fd, String[] args) {
    291         FileOutputStream fout = new FileOutputStream(fd);
    292         PrintWriter pw = new FastPrintWriter(fout);
    293         try {
    294             final String disabled;
    295             synchronized (Binder.class) {
    296                 disabled = sDumpDisabled;
    297             }
    298             if (disabled == null) {
    299                 try {
    300                     dump(fd, pw, args);
    301                 } catch (SecurityException e) {
    302                     pw.println("Security exception: " + e.getMessage());
    303                     throw e;
    304                 } catch (Throwable e) {
    305                     // Unlike usual calls, in this case if an exception gets thrown
    306                     // back to us we want to print it back in to the dump data, since
    307                     // that is where the caller expects all interesting information to
    308                     // go.
    309                     pw.println();
    310                     pw.println("Exception occurred while dumping:");
    311                     e.printStackTrace(pw);
    312                 }
    313             } else {
    314                 pw.println(sDumpDisabled);
    315             }
    316         } finally {
    317             pw.flush();
    318         }
    319     }
    320 
    321     /**
    322      * Like {@link #dump(FileDescriptor, String[])}, but ensures the target
    323      * executes asynchronously.
    324      */
    325     public void dumpAsync(final FileDescriptor fd, final String[] args) {
    326         final FileOutputStream fout = new FileOutputStream(fd);
    327         final PrintWriter pw = new FastPrintWriter(fout);
    328         Thread thr = new Thread("Binder.dumpAsync") {
    329             public void run() {
    330                 try {
    331                     dump(fd, pw, args);
    332                 } finally {
    333                     pw.flush();
    334                 }
    335             }
    336         };
    337         thr.start();
    338     }
    339 
    340     /**
    341      * Print the object's state into the given stream.
    342      *
    343      * @param fd The raw file descriptor that the dump is being sent to.
    344      * @param fout The file to which you should dump your state.  This will be
    345      * closed for you after you return.
    346      * @param args additional arguments to the dump request.
    347      */
    348     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
    349     }
    350 
    351     /**
    352      * Default implementation rewinds the parcels and calls onTransact.  On
    353      * the remote side, transact calls into the binder to do the IPC.
    354      */
    355     public final boolean transact(int code, Parcel data, Parcel reply,
    356             int flags) throws RemoteException {
    357         if (false) Log.v("Binder", "Transact: " + code + " to " + this);
    358         if (data != null) {
    359             data.setDataPosition(0);
    360         }
    361         boolean r = onTransact(code, data, reply, flags);
    362         if (reply != null) {
    363             reply.setDataPosition(0);
    364         }
    365         return r;
    366     }
    367 
    368     /**
    369      * Local implementation is a no-op.
    370      */
    371     public void linkToDeath(DeathRecipient recipient, int flags) {
    372     }
    373 
    374     /**
    375      * Local implementation is a no-op.
    376      */
    377     public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
    378         return true;
    379     }
    380 
    381     protected void finalize() throws Throwable {
    382         try {
    383             destroy();
    384         } finally {
    385             super.finalize();
    386         }
    387     }
    388 
    389     private native final void init();
    390     private native final void destroy();
    391 
    392     // Entry point from android_util_Binder.cpp's onTransact
    393     private boolean execTransact(int code, int dataObj, int replyObj,
    394             int flags) {
    395         Parcel data = Parcel.obtain(dataObj);
    396         Parcel reply = Parcel.obtain(replyObj);
    397         // theoretically, we should call transact, which will call onTransact,
    398         // but all that does is rewind it, and we just got these from an IPC,
    399         // so we'll just call it directly.
    400         boolean res;
    401         // Log any exceptions as warnings, don't silently suppress them.
    402         // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
    403         try {
    404             res = onTransact(code, data, reply, flags);
    405         } catch (RemoteException e) {
    406             if ((flags & FLAG_ONEWAY) != 0) {
    407                 Log.w(TAG, "Binder call failed.", e);
    408             }
    409             reply.setDataPosition(0);
    410             reply.writeException(e);
    411             res = true;
    412         } catch (RuntimeException e) {
    413             if ((flags & FLAG_ONEWAY) != 0) {
    414                 Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
    415             }
    416             reply.setDataPosition(0);
    417             reply.writeException(e);
    418             res = true;
    419         } catch (OutOfMemoryError e) {
    420             // Unconditionally log this, since this is generally unrecoverable.
    421             Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);
    422             RuntimeException re = new RuntimeException("Out of memory", e);
    423             reply.setDataPosition(0);
    424             reply.writeException(re);
    425             res = true;
    426         }
    427         reply.recycle();
    428         data.recycle();
    429         return res;
    430     }
    431 }
    432 
    433 final class BinderProxy implements IBinder {
    434     public native boolean pingBinder();
    435     public native boolean isBinderAlive();
    436 
    437     public IInterface queryLocalInterface(String descriptor) {
    438         return null;
    439     }
    440 
    441     public native String getInterfaceDescriptor() throws RemoteException;
    442     public native boolean transact(int code, Parcel data, Parcel reply,
    443             int flags) throws RemoteException;
    444     public native void linkToDeath(DeathRecipient recipient, int flags)
    445             throws RemoteException;
    446     public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
    447 
    448     public void dump(FileDescriptor fd, String[] args) throws RemoteException {
    449         Parcel data = Parcel.obtain();
    450         Parcel reply = Parcel.obtain();
    451         data.writeFileDescriptor(fd);
    452         data.writeStringArray(args);
    453         try {
    454             transact(DUMP_TRANSACTION, data, reply, 0);
    455             reply.readException();
    456         } finally {
    457             data.recycle();
    458             reply.recycle();
    459         }
    460     }
    461 
    462     public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
    463         Parcel data = Parcel.obtain();
    464         Parcel reply = Parcel.obtain();
    465         data.writeFileDescriptor(fd);
    466         data.writeStringArray(args);
    467         try {
    468             transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
    469         } finally {
    470             data.recycle();
    471             reply.recycle();
    472         }
    473     }
    474 
    475     BinderProxy() {
    476         mSelf = new WeakReference(this);
    477     }
    478 
    479     @Override
    480     protected void finalize() throws Throwable {
    481         try {
    482             destroy();
    483         } finally {
    484             super.finalize();
    485         }
    486     }
    487 
    488     private native final void destroy();
    489 
    490     private static final void sendDeathNotice(DeathRecipient recipient) {
    491         if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
    492         try {
    493             recipient.binderDied();
    494         }
    495         catch (RuntimeException exc) {
    496             Log.w("BinderNative", "Uncaught exception from death notification",
    497                     exc);
    498         }
    499     }
    500 
    501     final private WeakReference mSelf;
    502     private int mObject;
    503     private int mOrgue;
    504 }
    505