Binder.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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.Config;
20import android.util.Log;
21
22import java.io.FileDescriptor;
23import java.io.FileOutputStream;
24import java.io.IOException;
25import java.io.PrintWriter;
26import java.lang.ref.WeakReference;
27import 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/developing/tools/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 */
44public 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    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 to the local process.  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 back to a previously identity
95     * that was returned by {@link #clearCallingIdentity}.
96     *
97     * @param token The opaque token that was previously returned by
98     * {@link #clearCallingIdentity}.
99     *
100     * @see #clearCallingIdentity
101     */
102    public static final native void restoreCallingIdentity(long token);
103
104    /**
105     * Flush any Binder commands pending in the current thread to the kernel
106     * driver.  This can be
107     * useful to call before performing an operation that may block for a long
108     * time, to ensure that any pending object references have been released
109     * in order to prevent the process from holding on to objects longer than
110     * it needs to.
111     */
112    public static final native void flushPendingCommands();
113
114    /**
115     * Add the calling thread to the IPC thread pool.  This function does
116     * not return until the current process is exiting.
117     */
118    public static final native void joinThreadPool();
119
120    /**
121     * Default constructor initializes the object.
122     */
123    public Binder() {
124        init();
125
126        if (FIND_POTENTIAL_LEAKS) {
127            final Class<? extends Binder> klass = getClass();
128            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
129                    (klass.getModifiers() & Modifier.STATIC) == 0) {
130                Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
131                    klass.getCanonicalName());
132            }
133        }
134    }
135
136    /**
137     * Convenience method for associating a specific interface with the Binder.
138     * After calling, queryLocalInterface() will be implemented for you
139     * to return the given owner IInterface when the corresponding
140     * descriptor is requested.
141     */
142    public void attachInterface(IInterface owner, String descriptor) {
143        mOwner = owner;
144        mDescriptor = descriptor;
145    }
146
147    /**
148     * Default implementation returns an empty interface name.
149     */
150    public String getInterfaceDescriptor() {
151        return mDescriptor;
152    }
153
154    /**
155     * Default implementation always returns true -- if you got here,
156     * the object is alive.
157     */
158    public boolean pingBinder() {
159        return true;
160    }
161
162    /**
163     * {@inheritDoc}
164     *
165     * Note that if you're calling on a local binder, this always returns true
166     * because your process is alive if you're calling it.
167     */
168    public boolean isBinderAlive() {
169        return true;
170    }
171
172    /**
173     * Use information supplied to attachInterface() to return the
174     * associated IInterface if it matches the requested
175     * descriptor.
176     */
177    public IInterface queryLocalInterface(String descriptor) {
178        if (mDescriptor.equals(descriptor)) {
179            return mOwner;
180        }
181        return null;
182    }
183
184    /**
185     * Default implementation is a stub that returns false.  You will want
186     * to override this to do the appropriate unmarshalling of transactions.
187     *
188     * <p>If you want to call this, call transact().
189     */
190    protected boolean onTransact(int code, Parcel data, Parcel reply,
191            int flags) throws RemoteException {
192        if (code == INTERFACE_TRANSACTION) {
193            reply.writeString(getInterfaceDescriptor());
194            return true;
195        } else if (code == DUMP_TRANSACTION) {
196            ParcelFileDescriptor fd = data.readFileDescriptor();
197            String[] args = data.readStringArray();
198            if (fd != null) {
199                try {
200                    dump(fd.getFileDescriptor(), args);
201                } finally {
202                    try {
203                        fd.close();
204                    } catch (IOException e) {
205                    }
206                }
207            }
208            return true;
209        }
210        return false;
211    }
212
213    /**
214     * Implemented to call the more convenient version
215     * {@link #dump(FileDescriptor, PrintWriter, String[])}.
216     */
217    public void dump(FileDescriptor fd, String[] args) {
218        FileOutputStream fout = new FileOutputStream(fd);
219        PrintWriter pw = new PrintWriter(fout);
220        try {
221            dump(fd, pw, args);
222        } finally {
223            pw.flush();
224        }
225    }
226
227    /**
228     * Print the object's state into the given stream.
229     *
230     * @param fd The raw file descriptor that the dump is being sent to.
231     * @param fout The file to which you should dump your state.  This will be
232     * closed for you after you return.
233     * @param args additional arguments to the dump request.
234     */
235    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
236    }
237
238    /**
239     * Default implementation rewinds the parcels and calls onTransact.  On
240     * the remote side, transact calls into the binder to do the IPC.
241     */
242    public final boolean transact(int code, Parcel data, Parcel reply,
243            int flags) throws RemoteException {
244        if (Config.LOGV) Log.v("Binder", "Transact: " + code + " to " + this);
245        if (data != null) {
246            data.setDataPosition(0);
247        }
248        boolean r = onTransact(code, data, reply, flags);
249        if (reply != null) {
250            reply.setDataPosition(0);
251        }
252        return r;
253    }
254
255    /**
256     * Local implementation is a no-op.
257     */
258    public void linkToDeath(DeathRecipient recipient, int flags) {
259    }
260
261    /**
262     * Local implementation is a no-op.
263     */
264    public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
265        return true;
266    }
267
268    protected void finalize() throws Throwable {
269        try {
270            destroy();
271        } finally {
272            super.finalize();
273        }
274    }
275
276    private native final void init();
277    private native final void destroy();
278    private boolean execTransact(int code, int dataObj, int replyObj,
279            int flags) {
280        Parcel data = Parcel.obtain(dataObj);
281        Parcel reply = Parcel.obtain(replyObj);
282        // theoretically, we should call transact, which will call onTransact,
283        // but all that does is rewind it, and we just got these from an IPC,
284        // so we'll just call it directly.
285        boolean res;
286        try {
287            res = onTransact(code, data, reply, flags);
288        } catch (RemoteException e) {
289            reply.writeException(e);
290            res = true;
291        } catch (RuntimeException e) {
292            reply.writeException(e);
293            res = true;
294        }
295        reply.recycle();
296        data.recycle();
297        return res;
298    }
299}
300
301final class BinderProxy implements IBinder {
302    public native boolean pingBinder();
303    public native boolean isBinderAlive();
304
305    public IInterface queryLocalInterface(String descriptor) {
306        return null;
307    }
308
309    public native String getInterfaceDescriptor() throws RemoteException;
310    public native boolean transact(int code, Parcel data, Parcel reply,
311            int flags) throws RemoteException;
312    public native void linkToDeath(DeathRecipient recipient, int flags)
313            throws RemoteException;
314    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
315
316    public void dump(FileDescriptor fd, String[] args) throws RemoteException {
317        Parcel data = Parcel.obtain();
318        data.writeFileDescriptor(fd);
319        data.writeStringArray(args);
320        try {
321            transact(DUMP_TRANSACTION, data, null, 0);
322        } finally {
323            data.recycle();
324        }
325    }
326
327    BinderProxy() {
328        mSelf = new WeakReference(this);
329    }
330
331    @Override
332    protected void finalize() throws Throwable {
333        try {
334            destroy();
335        } finally {
336            super.finalize();
337        }
338    }
339
340    private native final void destroy();
341
342    private static final void sendDeathNotice(DeathRecipient recipient) {
343        if (Config.LOGV) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
344        try {
345            recipient.binderDied();
346        }
347        catch (RuntimeException exc) {
348            Log.w("BinderNative", "Uncaught exception from death notification",
349                    exc);
350        }
351    }
352
353    final private WeakReference mSelf;
354    private int mObject;
355}
356