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
17package android.os;
18
19import android.util.ExceptionUtils;
20import android.util.Log;
21import android.util.Slog;
22
23import com.android.internal.util.FastPrintWriter;
24import com.android.internal.util.FunctionalUtils;
25import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
26import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
27
28import libcore.io.IoUtils;
29
30import java.io.FileDescriptor;
31import java.io.FileOutputStream;
32import java.io.PrintWriter;
33import java.lang.ref.WeakReference;
34import java.lang.reflect.Modifier;
35
36/**
37 * Base class for a remotable object, the core part of a lightweight
38 * remote procedure call mechanism defined by {@link IBinder}.
39 * This class is an implementation of IBinder that provides
40 * standard local implementation of such an object.
41 *
42 * <p>Most developers will not implement this class directly, instead using the
43 * <a href="{@docRoot}guide/components/aidl.html">aidl</a> tool to describe the desired
44 * interface, having it generate the appropriate Binder subclass.  You can,
45 * however, derive directly from Binder to implement your own custom RPC
46 * protocol or simply instantiate a raw Binder object directly to use as a
47 * token that can be shared across processes.
48 *
49 * <p>This class is just a basic IPC primitive; it has no impact on an application's
50 * lifecycle, and is valid only as long as the process that created it continues to run.
51 * To use this correctly, you must be doing so within the context of a top-level
52 * application component (a {@link android.app.Service}, {@link android.app.Activity},
53 * or {@link android.content.ContentProvider}) that lets the system know your process
54 * should remain running.</p>
55 *
56 * <p>You must keep in mind the situations in which your process
57 * could go away, and thus require that you later re-create a new Binder and re-attach
58 * it when the process starts again.  For example, if you are using this within an
59 * {@link android.app.Activity}, your activity's process may be killed any time the
60 * activity is not started; if the activity is later re-created you will need to
61 * create a new Binder and hand it back to the correct place again; you need to be
62 * aware that your process may be started for another reason (for example to receive
63 * a broadcast) that will not involve re-creating the activity and thus run its code
64 * to create a new Binder.</p>
65 *
66 * @see IBinder
67 */
68public class Binder implements IBinder {
69    /*
70     * Set this flag to true to detect anonymous, local or member classes
71     * that extend this Binder class and that are not static. These kind
72     * of classes can potentially create leaks.
73     */
74    private static final boolean FIND_POTENTIAL_LEAKS = false;
75    /** @hide */
76    public static final boolean CHECK_PARCEL_SIZE = false;
77    static final String TAG = "Binder";
78
79    /** @hide */
80    public static boolean LOG_RUNTIME_EXCEPTION = false; // DO NOT SUBMIT WITH TRUE
81
82    /**
83     * Control whether dump() calls are allowed.
84     */
85    private static volatile String sDumpDisabled = null;
86
87    /**
88     * Global transaction tracker instance for this process.
89     */
90    private static volatile TransactionTracker sTransactionTracker = null;
91
92    // Transaction tracking code.
93
94    /**
95     * Flag indicating whether we should be tracing transact calls.
96     */
97    private static volatile boolean sTracingEnabled = false;
98
99    /**
100     * Enable Binder IPC tracing.
101     *
102     * @hide
103     */
104    public static void enableTracing() {
105        sTracingEnabled = true;
106    }
107
108    /**
109     * Disable Binder IPC tracing.
110     *
111     * @hide
112     */
113    public static void disableTracing() {
114        sTracingEnabled = false;
115    }
116
117    /**
118     * Check if binder transaction tracing is enabled.
119     *
120     * @hide
121     */
122    public static boolean isTracingEnabled() {
123        return sTracingEnabled;
124    }
125
126    /**
127     * Get the binder transaction tracker for this process.
128     *
129     * @hide
130     */
131    public synchronized static TransactionTracker getTransactionTracker() {
132        if (sTransactionTracker == null)
133            sTransactionTracker = new TransactionTracker();
134        return sTransactionTracker;
135    }
136
137    /** {@hide} */
138    static volatile boolean sWarnOnBlocking = false;
139
140    /**
141     * Warn if any blocking binder transactions are made out from this process.
142     * This is typically only useful for the system process, to prevent it from
143     * blocking on calls to external untrusted code. Instead, all outgoing calls
144     * that require a result must be sent as {@link IBinder#FLAG_ONEWAY} calls
145     * which deliver results through a callback interface.
146     *
147     * @hide
148     */
149    public static void setWarnOnBlocking(boolean warnOnBlocking) {
150        sWarnOnBlocking = warnOnBlocking;
151    }
152
153    /**
154     * Allow blocking calls on the given interface, overriding the requested
155     * value of {@link #setWarnOnBlocking(boolean)}.
156     * <p>
157     * This should only be rarely called when you are <em>absolutely sure</em>
158     * the remote interface is a built-in system component that can never be
159     * upgraded. In particular, this <em>must never</em> be called for
160     * interfaces hosted by package that could be upgraded or replaced,
161     * otherwise you risk system instability if that remote interface wedges.
162     *
163     * @hide
164     */
165    public static IBinder allowBlocking(IBinder binder) {
166        try {
167            if (binder instanceof BinderProxy) {
168                ((BinderProxy) binder).mWarnOnBlocking = false;
169            } else if (binder != null
170                    && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
171                Log.w(TAG, "Unable to allow blocking on interface " + binder);
172            }
173        } catch (RemoteException ignored) {
174        }
175        return binder;
176    }
177
178    /**
179     * Inherit the current {@link #allowBlocking(IBinder)} value from one given
180     * interface to another.
181     *
182     * @hide
183     */
184    public static void copyAllowBlocking(IBinder fromBinder, IBinder toBinder) {
185        if (fromBinder instanceof BinderProxy && toBinder instanceof BinderProxy) {
186            ((BinderProxy) toBinder).mWarnOnBlocking = ((BinderProxy) fromBinder).mWarnOnBlocking;
187        }
188    }
189
190    /* mObject is used by native code, do not remove or rename */
191    private long mObject;
192    private IInterface mOwner;
193    private String mDescriptor;
194
195    /**
196     * Return the ID of the process that sent you the current transaction
197     * that is being processed.  This pid can be used with higher-level
198     * system services to determine its identity and check permissions.
199     * If the current thread is not currently executing an incoming transaction,
200     * then its own pid is returned.
201     */
202    public static final native int getCallingPid();
203
204    /**
205     * Return the Linux uid assigned to the process that sent you the
206     * current transaction that is being processed.  This uid can be used with
207     * higher-level system services to determine its identity and check
208     * permissions.  If the current thread is not currently executing an
209     * incoming transaction, then its own uid is returned.
210     */
211    public static final native int getCallingUid();
212
213    /**
214     * Return the UserHandle assigned to the process that sent you the
215     * current transaction that is being processed.  This is the user
216     * of the caller.  It is distinct from {@link #getCallingUid()} in that a
217     * particular user will have multiple distinct apps running under it each
218     * with their own uid.  If the current thread is not currently executing an
219     * incoming transaction, then its own UserHandle is returned.
220     */
221    public static final UserHandle getCallingUserHandle() {
222        return UserHandle.of(UserHandle.getUserId(getCallingUid()));
223    }
224
225    /**
226     * Reset the identity of the incoming IPC on the current thread.  This can
227     * be useful if, while handling an incoming call, you will be calling
228     * on interfaces of other objects that may be local to your process and
229     * need to do permission checks on the calls coming into them (so they
230     * will check the permission of your own local process, and not whatever
231     * process originally called you).
232     *
233     * @return Returns an opaque token that can be used to restore the
234     * original calling identity by passing it to
235     * {@link #restoreCallingIdentity(long)}.
236     *
237     * @see #getCallingPid()
238     * @see #getCallingUid()
239     * @see #restoreCallingIdentity(long)
240     */
241    public static final native long clearCallingIdentity();
242
243    /**
244     * Restore the identity of the incoming IPC on the current thread
245     * back to a previously identity that was returned by {@link
246     * #clearCallingIdentity}.
247     *
248     * @param token The opaque token that was previously returned by
249     * {@link #clearCallingIdentity}.
250     *
251     * @see #clearCallingIdentity
252     */
253    public static final native void restoreCallingIdentity(long token);
254
255    /**
256     * Convenience method for running the provided action enclosed in
257     * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}
258     *
259     * Any exception thrown by the given action will be caught and rethrown after the call to
260     * {@link #restoreCallingIdentity}
261     *
262     * @hide
263     */
264    public static final void withCleanCallingIdentity(ThrowingRunnable action) {
265        long callingIdentity = clearCallingIdentity();
266        Throwable throwableToPropagate = null;
267        try {
268            action.run();
269        } catch (Throwable throwable) {
270            throwableToPropagate = throwable;
271        } finally {
272            restoreCallingIdentity(callingIdentity);
273            if (throwableToPropagate != null) {
274                throw ExceptionUtils.propagate(throwableToPropagate);
275            }
276        }
277    }
278
279    /**
280     * Convenience method for running the provided action enclosed in
281     * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result
282     *
283     * Any exception thrown by the given action will be caught and rethrown after the call to
284     * {@link #restoreCallingIdentity}
285     *
286     * @hide
287     */
288    public static final <T> T withCleanCallingIdentity(ThrowingSupplier<T> action) {
289        long callingIdentity = clearCallingIdentity();
290        Throwable throwableToPropagate = null;
291        try {
292            return action.get();
293        } catch (Throwable throwable) {
294            throwableToPropagate = throwable;
295            return null; // overridden by throwing in finally block
296        } finally {
297            restoreCallingIdentity(callingIdentity);
298            if (throwableToPropagate != null) {
299                throw ExceptionUtils.propagate(throwableToPropagate);
300            }
301        }
302    }
303
304    /**
305     * Sets the native thread-local StrictMode policy mask.
306     *
307     * <p>The StrictMode settings are kept in two places: a Java-level
308     * threadlocal for libcore/Dalvik, and a native threadlocal (set
309     * here) for propagation via Binder calls.  This is a little
310     * unfortunate, but necessary to break otherwise more unfortunate
311     * dependencies either of Dalvik on Android, or Android
312     * native-only code on Dalvik.
313     *
314     * @see StrictMode
315     * @hide
316     */
317    public static final native void setThreadStrictModePolicy(int policyMask);
318
319    /**
320     * Gets the current native thread-local StrictMode policy mask.
321     *
322     * @see #setThreadStrictModePolicy
323     * @hide
324     */
325    public static final native int getThreadStrictModePolicy();
326
327    /**
328     * Flush any Binder commands pending in the current thread to the kernel
329     * driver.  This can be
330     * useful to call before performing an operation that may block for a long
331     * time, to ensure that any pending object references have been released
332     * in order to prevent the process from holding on to objects longer than
333     * it needs to.
334     */
335    public static final native void flushPendingCommands();
336
337    /**
338     * Add the calling thread to the IPC thread pool.  This function does
339     * not return until the current process is exiting.
340     */
341    public static final native void joinThreadPool();
342
343    /**
344     * Returns true if the specified interface is a proxy.
345     * @hide
346     */
347    public static final boolean isProxy(IInterface iface) {
348        return iface.asBinder() != iface;
349    }
350
351    /**
352     * Call blocks until the number of executing binder threads is less
353     * than the maximum number of binder threads allowed for this process.
354     * @hide
355     */
356    public static final native void blockUntilThreadAvailable();
357
358    /**
359     * Default constructor initializes the object.
360     */
361    public Binder() {
362        init();
363
364        if (FIND_POTENTIAL_LEAKS) {
365            final Class<? extends Binder> klass = getClass();
366            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
367                    (klass.getModifiers() & Modifier.STATIC) == 0) {
368                Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
369                    klass.getCanonicalName());
370            }
371        }
372    }
373
374    /**
375     * Convenience method for associating a specific interface with the Binder.
376     * After calling, queryLocalInterface() will be implemented for you
377     * to return the given owner IInterface when the corresponding
378     * descriptor is requested.
379     */
380    public void attachInterface(IInterface owner, String descriptor) {
381        mOwner = owner;
382        mDescriptor = descriptor;
383    }
384
385    /**
386     * Default implementation returns an empty interface name.
387     */
388    public String getInterfaceDescriptor() {
389        return mDescriptor;
390    }
391
392    /**
393     * Default implementation always returns true -- if you got here,
394     * the object is alive.
395     */
396    public boolean pingBinder() {
397        return true;
398    }
399
400    /**
401     * {@inheritDoc}
402     *
403     * Note that if you're calling on a local binder, this always returns true
404     * because your process is alive if you're calling it.
405     */
406    public boolean isBinderAlive() {
407        return true;
408    }
409
410    /**
411     * Use information supplied to attachInterface() to return the
412     * associated IInterface if it matches the requested
413     * descriptor.
414     */
415    public IInterface queryLocalInterface(String descriptor) {
416        if (mDescriptor.equals(descriptor)) {
417            return mOwner;
418        }
419        return null;
420    }
421
422    /**
423     * Control disabling of dump calls in this process.  This is used by the system
424     * process watchdog to disable incoming dump calls while it has detecting the system
425     * is hung and is reporting that back to the activity controller.  This is to
426     * prevent the controller from getting hung up on bug reports at this point.
427     * @hide
428     *
429     * @param msg The message to show instead of the dump; if null, dumps are
430     * re-enabled.
431     */
432    public static void setDumpDisabled(String msg) {
433        sDumpDisabled = msg;
434    }
435
436    /**
437     * Default implementation is a stub that returns false.  You will want
438     * to override this to do the appropriate unmarshalling of transactions.
439     *
440     * <p>If you want to call this, call transact().
441     */
442    protected boolean onTransact(int code, Parcel data, Parcel reply,
443            int flags) throws RemoteException {
444        if (code == INTERFACE_TRANSACTION) {
445            reply.writeString(getInterfaceDescriptor());
446            return true;
447        } else if (code == DUMP_TRANSACTION) {
448            ParcelFileDescriptor fd = data.readFileDescriptor();
449            String[] args = data.readStringArray();
450            if (fd != null) {
451                try {
452                    dump(fd.getFileDescriptor(), args);
453                } finally {
454                    IoUtils.closeQuietly(fd);
455                }
456            }
457            // Write the StrictMode header.
458            if (reply != null) {
459                reply.writeNoException();
460            } else {
461                StrictMode.clearGatheredViolations();
462            }
463            return true;
464        } else if (code == SHELL_COMMAND_TRANSACTION) {
465            ParcelFileDescriptor in = data.readFileDescriptor();
466            ParcelFileDescriptor out = data.readFileDescriptor();
467            ParcelFileDescriptor err = data.readFileDescriptor();
468            String[] args = data.readStringArray();
469            ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
470            ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
471            try {
472                if (out != null) {
473                    shellCommand(in != null ? in.getFileDescriptor() : null,
474                            out.getFileDescriptor(),
475                            err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
476                            args, shellCallback, resultReceiver);
477                }
478            } finally {
479                IoUtils.closeQuietly(in);
480                IoUtils.closeQuietly(out);
481                IoUtils.closeQuietly(err);
482                // Write the StrictMode header.
483                if (reply != null) {
484                    reply.writeNoException();
485                } else {
486                    StrictMode.clearGatheredViolations();
487                }
488            }
489            return true;
490        }
491        return false;
492    }
493
494    /**
495     * Implemented to call the more convenient version
496     * {@link #dump(FileDescriptor, PrintWriter, String[])}.
497     */
498    public void dump(FileDescriptor fd, String[] args) {
499        FileOutputStream fout = new FileOutputStream(fd);
500        PrintWriter pw = new FastPrintWriter(fout);
501        try {
502            doDump(fd, pw, args);
503        } finally {
504            pw.flush();
505        }
506    }
507
508    void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
509        final String disabled = sDumpDisabled;
510        if (disabled == null) {
511            try {
512                dump(fd, pw, args);
513            } catch (SecurityException e) {
514                pw.println("Security exception: " + e.getMessage());
515                throw e;
516            } catch (Throwable e) {
517                // Unlike usual calls, in this case if an exception gets thrown
518                // back to us we want to print it back in to the dump data, since
519                // that is where the caller expects all interesting information to
520                // go.
521                pw.println();
522                pw.println("Exception occurred while dumping:");
523                e.printStackTrace(pw);
524            }
525        } else {
526            pw.println(sDumpDisabled);
527        }
528    }
529
530    /**
531     * Like {@link #dump(FileDescriptor, String[])}, but ensures the target
532     * executes asynchronously.
533     */
534    public void dumpAsync(final FileDescriptor fd, final String[] args) {
535        final FileOutputStream fout = new FileOutputStream(fd);
536        final PrintWriter pw = new FastPrintWriter(fout);
537        Thread thr = new Thread("Binder.dumpAsync") {
538            public void run() {
539                try {
540                    dump(fd, pw, args);
541                } finally {
542                    pw.flush();
543                }
544            }
545        };
546        thr.start();
547    }
548
549    /**
550     * Print the object's state into the given stream.
551     *
552     * @param fd The raw file descriptor that the dump is being sent to.
553     * @param fout The file to which you should dump your state.  This will be
554     * closed for you after you return.
555     * @param args additional arguments to the dump request.
556     */
557    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
558    }
559
560    /**
561     * @param in The raw file descriptor that an input data stream can be read from.
562     * @param out The raw file descriptor that normal command messages should be written to.
563     * @param err The raw file descriptor that command error messages should be written to.
564     * @param args Command-line arguments.
565     * @param callback Callback through which to interact with the invoking shell.
566     * @param resultReceiver Called when the command has finished executing, with the result code.
567     * @throws RemoteException
568     * @hide
569     */
570    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
571            String[] args, ShellCallback callback,
572            ResultReceiver resultReceiver) throws RemoteException {
573        onShellCommand(in, out, err, args, callback, resultReceiver);
574    }
575
576    /**
577     * Handle a call to {@link #shellCommand}.  The default implementation simply prints
578     * an error message.  Override and replace with your own.
579     * <p class="caution">Note: no permission checking is done before calling this method; you must
580     * apply any security checks as appropriate for the command being executed.
581     * Consider using {@link ShellCommand} to help in the implementation.</p>
582     * @hide
583     */
584    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
585            String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException {
586        FileOutputStream fout = new FileOutputStream(err != null ? err : out);
587        PrintWriter pw = new FastPrintWriter(fout);
588        pw.println("No shell command implementation.");
589        pw.flush();
590        resultReceiver.send(0, null);
591    }
592
593    /**
594     * Default implementation rewinds the parcels and calls onTransact.  On
595     * the remote side, transact calls into the binder to do the IPC.
596     */
597    public final boolean transact(int code, Parcel data, Parcel reply,
598            int flags) throws RemoteException {
599        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
600
601        if (data != null) {
602            data.setDataPosition(0);
603        }
604        boolean r = onTransact(code, data, reply, flags);
605        if (reply != null) {
606            reply.setDataPosition(0);
607        }
608        return r;
609    }
610
611    /**
612     * Local implementation is a no-op.
613     */
614    public void linkToDeath(DeathRecipient recipient, int flags) {
615    }
616
617    /**
618     * Local implementation is a no-op.
619     */
620    public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
621        return true;
622    }
623
624    protected void finalize() throws Throwable {
625        try {
626            destroy();
627        } finally {
628            super.finalize();
629        }
630    }
631
632    static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {
633        if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {
634            // Trying to send > 800k, this is way too much
635            StringBuilder sb = new StringBuilder();
636            sb.append(msg);
637            sb.append(": on ");
638            sb.append(obj);
639            sb.append(" calling ");
640            sb.append(code);
641            sb.append(" size ");
642            sb.append(parcel.dataSize());
643            sb.append(" (data: ");
644            parcel.setDataPosition(0);
645            sb.append(parcel.readInt());
646            sb.append(", ");
647            sb.append(parcel.readInt());
648            sb.append(", ");
649            sb.append(parcel.readInt());
650            sb.append(")");
651            Slog.wtfStack(TAG, sb.toString());
652        }
653    }
654
655    private native final void init();
656    private native final void destroy();
657
658    // Entry point from android_util_Binder.cpp's onTransact
659    private boolean execTransact(int code, long dataObj, long replyObj,
660            int flags) {
661        Parcel data = Parcel.obtain(dataObj);
662        Parcel reply = Parcel.obtain(replyObj);
663        // theoretically, we should call transact, which will call onTransact,
664        // but all that does is rewind it, and we just got these from an IPC,
665        // so we'll just call it directly.
666        boolean res;
667        // Log any exceptions as warnings, don't silently suppress them.
668        // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
669        final boolean tracingEnabled = Binder.isTracingEnabled();
670        try {
671            if (tracingEnabled) {
672                Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
673            }
674            res = onTransact(code, data, reply, flags);
675        } catch (RemoteException|RuntimeException e) {
676            if (LOG_RUNTIME_EXCEPTION) {
677                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
678            }
679            if ((flags & FLAG_ONEWAY) != 0) {
680                if (e instanceof RemoteException) {
681                    Log.w(TAG, "Binder call failed.", e);
682                } else {
683                    Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
684                }
685            } else {
686                reply.setDataPosition(0);
687                reply.writeException(e);
688            }
689            res = true;
690        } catch (OutOfMemoryError e) {
691            // Unconditionally log this, since this is generally unrecoverable.
692            Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);
693            RuntimeException re = new RuntimeException("Out of memory", e);
694            reply.setDataPosition(0);
695            reply.writeException(re);
696            res = true;
697        } finally {
698            if (tracingEnabled) {
699                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
700            }
701        }
702        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
703        reply.recycle();
704        data.recycle();
705
706        // Just in case -- we are done with the IPC, so there should be no more strict
707        // mode violations that have gathered for this thread.  Either they have been
708        // parceled and are now in transport off to the caller, or we are returning back
709        // to the main transaction loop to wait for another incoming transaction.  Either
710        // way, strict mode begone!
711        StrictMode.clearGatheredViolations();
712
713        return res;
714    }
715}
716
717final class BinderProxy implements IBinder {
718    // Assume the process-wide default value when created
719    volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
720
721    public native boolean pingBinder();
722    public native boolean isBinderAlive();
723
724    public IInterface queryLocalInterface(String descriptor) {
725        return null;
726    }
727
728    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
729        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
730
731        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
732            // For now, avoid spamming the log by disabling after we've logged
733            // about this interface at least once
734            mWarnOnBlocking = false;
735            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
736                    new Throwable());
737        }
738
739        final boolean tracingEnabled = Binder.isTracingEnabled();
740        if (tracingEnabled) {
741            final Throwable tr = new Throwable();
742            Binder.getTransactionTracker().addTrace(tr);
743            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
744            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
745                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
746        }
747        try {
748            return transactNative(code, data, reply, flags);
749        } finally {
750            if (tracingEnabled) {
751                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
752            }
753        }
754    }
755
756    public native String getInterfaceDescriptor() throws RemoteException;
757    public native boolean transactNative(int code, Parcel data, Parcel reply,
758            int flags) throws RemoteException;
759    public native void linkToDeath(DeathRecipient recipient, int flags)
760            throws RemoteException;
761    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
762
763    public void dump(FileDescriptor fd, String[] args) throws RemoteException {
764        Parcel data = Parcel.obtain();
765        Parcel reply = Parcel.obtain();
766        data.writeFileDescriptor(fd);
767        data.writeStringArray(args);
768        try {
769            transact(DUMP_TRANSACTION, data, reply, 0);
770            reply.readException();
771        } finally {
772            data.recycle();
773            reply.recycle();
774        }
775    }
776
777    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
778        Parcel data = Parcel.obtain();
779        Parcel reply = Parcel.obtain();
780        data.writeFileDescriptor(fd);
781        data.writeStringArray(args);
782        try {
783            transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
784        } finally {
785            data.recycle();
786            reply.recycle();
787        }
788    }
789
790    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
791            String[] args, ShellCallback callback,
792            ResultReceiver resultReceiver) throws RemoteException {
793        Parcel data = Parcel.obtain();
794        Parcel reply = Parcel.obtain();
795        data.writeFileDescriptor(in);
796        data.writeFileDescriptor(out);
797        data.writeFileDescriptor(err);
798        data.writeStringArray(args);
799        ShellCallback.writeToParcel(callback, data);
800        resultReceiver.writeToParcel(data, 0);
801        try {
802            transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
803            reply.readException();
804        } finally {
805            data.recycle();
806            reply.recycle();
807        }
808    }
809
810    BinderProxy() {
811        mSelf = new WeakReference(this);
812    }
813
814    @Override
815    protected void finalize() throws Throwable {
816        try {
817            destroy();
818        } finally {
819            super.finalize();
820        }
821    }
822
823    private native final void destroy();
824
825    private static final void sendDeathNotice(DeathRecipient recipient) {
826        if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
827        try {
828            recipient.binderDied();
829        }
830        catch (RuntimeException exc) {
831            Log.w("BinderNative", "Uncaught exception from death notification",
832                    exc);
833        }
834    }
835
836    final private WeakReference mSelf;
837    private long mObject;
838    private long mOrgue;
839}
840