• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 import java.io.FileDescriptor;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.PrintWriter;
25 import java.lang.ref.WeakReference;
26 import 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  */
43 public 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      */
getCallingPid()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      */
getCallingUid()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      */
clearCallingIdentity()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      */
restoreCallingIdentity(long token)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      */
setThreadStrictModePolicy(int policyMask)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      */
getThreadStrictModePolicy()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      */
flushPendingCommands()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      */
joinThreadPool()141     public static final native void joinThreadPool();
142 
143     /**
144      * Default constructor initializes the object.
145      */
Binder()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      */
attachInterface(IInterface owner, String descriptor)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      */
getInterfaceDescriptor()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      */
pingBinder()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      */
isBinderAlive()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      */
queryLocalInterface(String descriptor)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      */
onTransact(int code, Parcel data, Parcel reply, int flags)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      */
dump(FileDescriptor fd, String[] args)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      */
dumpAsync(final FileDescriptor fd, final String[] args)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      */
dump(FileDescriptor fd, PrintWriter fout, String[] args)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      */
transact(int code, Parcel data, Parcel reply, int flags)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      */
linkToDeath(DeathRecipient recipient, int flags)307     public void linkToDeath(DeathRecipient recipient, int flags) {
308     }
309 
310     /**
311      * Local implementation is a no-op.
312      */
unlinkToDeath(DeathRecipient recipient, int flags)313     public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
314         return true;
315     }
316 
finalize()317     protected void finalize() throws Throwable {
318         try {
319             destroy();
320         } finally {
321             super.finalize();
322         }
323     }
324 
init()325     private native final void init();
destroy()326     private native final void destroy();
327 
328     // Entry point from android_util_Binder.cpp's onTransact
execTransact(int code, int dataObj, int replyObj, int flags)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 
356 final class BinderProxy implements IBinder {
pingBinder()357     public native boolean pingBinder();
isBinderAlive()358     public native boolean isBinderAlive();
359 
queryLocalInterface(String descriptor)360     public IInterface queryLocalInterface(String descriptor) {
361         return null;
362     }
363 
getInterfaceDescriptor()364     public native String getInterfaceDescriptor() throws RemoteException;
transact(int code, Parcel data, Parcel reply, int flags)365     public native boolean transact(int code, Parcel data, Parcel reply,
366             int flags) throws RemoteException;
linkToDeath(DeathRecipient recipient, int flags)367     public native void linkToDeath(DeathRecipient recipient, int flags)
368             throws RemoteException;
unlinkToDeath(DeathRecipient recipient, int flags)369     public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
370 
dump(FileDescriptor fd, String[] args)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 
dumpAsync(FileDescriptor fd, String[] args)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 
BinderProxy()399     BinderProxy() {
400         mSelf = new WeakReference(this);
401     }
402 
403     @Override
finalize()404     protected void finalize() throws Throwable {
405         try {
406             destroy();
407         } finally {
408             super.finalize();
409         }
410     }
411 
destroy()412     private native final void destroy();
413 
sendDeathNotice(DeathRecipient recipient)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