Binder.java revision 4120375d46091df8527bb701882e056fbb0e6b06
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.Log;
20
21import java.io.FileDescriptor;
22import java.io.FileOutputStream;
23import java.io.IOException;
24import java.io.PrintWriter;
25import java.lang.ref.WeakReference;
26import java.lang.reflect.Modifier;
27
28/**
29 * Base class for a remotable object, the core part of a lightweight
30 * remote procedure call mechanism defined by {@link IBinder}.
31 * This class is an implementation of IBinder that provides
32 * the standard support creating a local implementation of such an object.
33 *
34 * <p>Most developers will not implement this class directly, instead using the
35 * <a href="{@docRoot}guide/components/aidl.html">aidl</a> tool to describe the desired
36 * interface, having it generate the appropriate Binder subclass.  You can,
37 * however, derive directly from Binder to implement your own custom RPC
38 * protocol or simply instantiate a raw Binder object directly to use as a
39 * token that can be shared across processes.
40 *
41 * @see IBinder
42 */
43public class Binder implements IBinder {
44    /*
45     * Set this flag to true to detect anonymous, local or member classes
46     * that extend this Binder class and that are not static. These kind
47     * of classes can potentially create leaks.
48     */
49    private static final boolean FIND_POTENTIAL_LEAKS = false;
50    private static final String TAG = "Binder";
51
52    /* mObject is used by native code, do not remove or rename */
53    private int mObject;
54    private IInterface mOwner;
55    private String mDescriptor;
56
57    /**
58     * Return the ID of the process that sent you the current transaction
59     * that is being processed.  This pid can be used with higher-level
60     * system services to determine its identity and check permissions.
61     * If the current thread is not currently executing an incoming transaction,
62     * then its own pid is returned.
63     */
64    public static final native int getCallingPid();
65
66    /**
67     * Return the ID of the user assigned to the process that sent you the
68     * current transaction that is being processed.  This uid can be used with
69     * higher-level system services to determine its identity and check
70     * permissions.  If the current thread is not currently executing an
71     * incoming transaction, then its own uid is returned.
72     */
73    public static final native int getCallingUid();
74
75    /**
76     * Reset the identity of the incoming IPC on the current thread.  This can
77     * be useful if, while handling an incoming call, you will be calling
78     * on interfaces of other objects that may be local to your process and
79     * need to do permission checks on the calls coming into them (so they
80     * will check the permission of your own local process, and not whatever
81     * process originally called you).
82     *
83     * @return Returns an opaque token that can be used to restore the
84     * original calling identity by passing it to
85     * {@link #restoreCallingIdentity(long)}.
86     *
87     * @see #getCallingPid()
88     * @see #getCallingUid()
89     * @see #restoreCallingIdentity(long)
90     */
91    public static final native long clearCallingIdentity();
92
93    /**
94     * Restore the identity of the incoming IPC on the current thread
95     * back to a previously identity that was returned by {@link
96     * #clearCallingIdentity}.
97     *
98     * @param token The opaque token that was previously returned by
99     * {@link #clearCallingIdentity}.
100     *
101     * @see #clearCallingIdentity
102     */
103    public static final native void restoreCallingIdentity(long token);
104
105    /**
106     * Sets the native thread-local StrictMode policy mask.
107     *
108     * <p>The StrictMode settings are kept in two places: a Java-level
109     * threadlocal for libcore/Dalvik, and a native threadlocal (set
110     * here) for propagation via Binder calls.  This is a little
111     * unfortunate, but necessary to break otherwise more unfortunate
112     * dependencies either of Dalvik on Android, or Android
113     * native-only code on Dalvik.
114     *
115     * @see StrictMode
116     * @hide
117     */
118    public static final native void setThreadStrictModePolicy(int policyMask);
119
120    /**
121     * Gets the current native thread-local StrictMode policy mask.
122     *
123     * @see #setThreadStrictModePolicy
124     * @hide
125     */
126    public static final native int getThreadStrictModePolicy();
127
128    /**
129     * Flush any Binder commands pending in the current thread to the kernel
130     * driver.  This can be
131     * useful to call before performing an operation that may block for a long
132     * time, to ensure that any pending object references have been released
133     * in order to prevent the process from holding on to objects longer than
134     * it needs to.
135     */
136    public static final native void flushPendingCommands();
137
138    /**
139     * Add the calling thread to the IPC thread pool.  This function does
140     * not return until the current process is exiting.
141     */
142    public static final native void joinThreadPool();
143
144    /**
145     * Default constructor initializes the object.
146     */
147    public Binder() {
148        init();
149
150        if (FIND_POTENTIAL_LEAKS) {
151            final Class<? extends Binder> klass = getClass();
152            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
153                    (klass.getModifiers() & Modifier.STATIC) == 0) {
154                Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
155                    klass.getCanonicalName());
156            }
157        }
158    }
159
160    /**
161     * Convenience method for associating a specific interface with the Binder.
162     * After calling, queryLocalInterface() will be implemented for you
163     * to return the given owner IInterface when the corresponding
164     * descriptor is requested.
165     */
166    public void attachInterface(IInterface owner, String descriptor) {
167        mOwner = owner;
168        mDescriptor = descriptor;
169    }
170
171    /**
172     * Default implementation returns an empty interface name.
173     */
174    public String getInterfaceDescriptor() {
175        return mDescriptor;
176    }
177
178    /**
179     * Default implementation always returns true -- if you got here,
180     * the object is alive.
181     */
182    public boolean pingBinder() {
183        return true;
184    }
185
186    /**
187     * {@inheritDoc}
188     *
189     * Note that if you're calling on a local binder, this always returns true
190     * because your process is alive if you're calling it.
191     */
192    public boolean isBinderAlive() {
193        return true;
194    }
195
196    /**
197     * Use information supplied to attachInterface() to return the
198     * associated IInterface if it matches the requested
199     * descriptor.
200     */
201    public IInterface queryLocalInterface(String descriptor) {
202        if (mDescriptor.equals(descriptor)) {
203            return mOwner;
204        }
205        return null;
206    }
207
208    /**
209     * Default implementation is a stub that returns false.  You will want
210     * to override this to do the appropriate unmarshalling of transactions.
211     *
212     * <p>If you want to call this, call transact().
213     */
214    protected boolean onTransact(int code, Parcel data, Parcel reply,
215            int flags) throws RemoteException {
216        if (code == INTERFACE_TRANSACTION) {
217            reply.writeString(getInterfaceDescriptor());
218            return true;
219        } else if (code == DUMP_TRANSACTION) {
220            ParcelFileDescriptor fd = data.readFileDescriptor();
221            String[] args = data.readStringArray();
222            if (fd != null) {
223                try {
224                    dump(fd.getFileDescriptor(), args);
225                } finally {
226                    try {
227                        fd.close();
228                    } catch (IOException e) {
229                        // swallowed, not propagated back to the caller
230                    }
231                }
232            }
233            // Write the StrictMode header.
234            if (reply != null) {
235                reply.writeNoException();
236            } else {
237                StrictMode.clearGatheredViolations();
238            }
239            return true;
240        }
241        return false;
242    }
243
244    /**
245     * Implemented to call the more convenient version
246     * {@link #dump(FileDescriptor, PrintWriter, String[])}.
247     */
248    public void dump(FileDescriptor fd, String[] args) {
249        FileOutputStream fout = new FileOutputStream(fd);
250        PrintWriter pw = new PrintWriter(fout);
251        try {
252            dump(fd, pw, args);
253        } finally {
254            pw.flush();
255        }
256    }
257
258    /**
259     * Like {@link #dump(FileDescriptor, String[])}, but ensures the target
260     * executes asynchronously.
261     */
262    public void dumpAsync(final FileDescriptor fd, final String[] args) {
263        final FileOutputStream fout = new FileOutputStream(fd);
264        final PrintWriter pw = new PrintWriter(fout);
265        Thread thr = new Thread("Binder.dumpAsync") {
266            public void run() {
267                try {
268                    dump(fd, pw, args);
269                } finally {
270                    pw.flush();
271                }
272            }
273        };
274        thr.start();
275    }
276
277    /**
278     * Print the object's state into the given stream.
279     *
280     * @param fd The raw file descriptor that the dump is being sent to.
281     * @param fout The file to which you should dump your state.  This will be
282     * closed for you after you return.
283     * @param args additional arguments to the dump request.
284     */
285    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
286    }
287
288    /**
289     * Default implementation rewinds the parcels and calls onTransact.  On
290     * the remote side, transact calls into the binder to do the IPC.
291     */
292    public final boolean transact(int code, Parcel data, Parcel reply,
293            int flags) throws RemoteException {
294        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
295        if (data != null) {
296            data.setDataPosition(0);
297        }
298        boolean r = onTransact(code, data, reply, flags);
299        if (reply != null) {
300            reply.setDataPosition(0);
301        }
302        return r;
303    }
304
305    /**
306     * Local implementation is a no-op.
307     */
308    public void linkToDeath(DeathRecipient recipient, int flags) {
309    }
310
311    /**
312     * Local implementation is a no-op.
313     */
314    public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
315        return true;
316    }
317
318    protected void finalize() throws Throwable {
319        try {
320            destroy();
321        } finally {
322            super.finalize();
323        }
324    }
325
326    private native final void init();
327    private native final void destroy();
328
329    // Entry point from android_util_Binder.cpp's onTransact
330    private boolean execTransact(int code, int dataObj, int replyObj,
331            int flags) {
332        Parcel data = Parcel.obtain(dataObj);
333        Parcel reply = Parcel.obtain(replyObj);
334        // theoretically, we should call transact, which will call onTransact,
335        // but all that does is rewind it, and we just got these from an IPC,
336        // so we'll just call it directly.
337        boolean res;
338        try {
339            res = onTransact(code, data, reply, flags);
340        } catch (RemoteException e) {
341            reply.setDataPosition(0);
342            reply.writeException(e);
343            res = true;
344        } catch (RuntimeException e) {
345            reply.setDataPosition(0);
346            reply.writeException(e);
347            res = true;
348        } catch (OutOfMemoryError e) {
349            RuntimeException re = new RuntimeException("Out of memory", e);
350            reply.setDataPosition(0);
351            reply.writeException(re);
352            res = true;
353        }
354        reply.recycle();
355        data.recycle();
356        return res;
357    }
358}
359
360final class BinderProxy implements IBinder {
361    public native boolean pingBinder();
362    public native boolean isBinderAlive();
363
364    public IInterface queryLocalInterface(String descriptor) {
365        return null;
366    }
367
368    public native String getInterfaceDescriptor() throws RemoteException;
369    public native boolean transact(int code, Parcel data, Parcel reply,
370            int flags) throws RemoteException;
371    public native void linkToDeath(DeathRecipient recipient, int flags)
372            throws RemoteException;
373    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
374
375    public void dump(FileDescriptor fd, String[] args) throws RemoteException {
376        Parcel data = Parcel.obtain();
377        Parcel reply = Parcel.obtain();
378        data.writeFileDescriptor(fd);
379        data.writeStringArray(args);
380        try {
381            transact(DUMP_TRANSACTION, data, reply, 0);
382            reply.readException();
383        } finally {
384            data.recycle();
385            reply.recycle();
386        }
387    }
388
389    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
390        Parcel data = Parcel.obtain();
391        Parcel reply = Parcel.obtain();
392        data.writeFileDescriptor(fd);
393        data.writeStringArray(args);
394        try {
395            transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
396            reply.readException();
397        } finally {
398            data.recycle();
399            reply.recycle();
400        }
401    }
402
403    BinderProxy() {
404        mSelf = new WeakReference(this);
405    }
406
407    @Override
408    protected void finalize() throws Throwable {
409        try {
410            destroy();
411        } finally {
412            super.finalize();
413        }
414    }
415
416    private native final void destroy();
417
418    private static final void sendDeathNotice(DeathRecipient recipient) {
419        if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
420        try {
421            recipient.binderDied();
422        }
423        catch (RuntimeException exc) {
424            Log.w("BinderNative", "Uncaught exception from death notification",
425                    exc);
426        }
427    }
428
429    final private WeakReference mSelf;
430    private int mObject;
431    private int mOrgue;
432}
433