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