• 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.Config;
20 import android.util.Log;
21 
22 import java.io.FileDescriptor;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.PrintWriter;
26 import java.lang.ref.WeakReference;
27 import 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  */
44 public 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      */
getCallingPid()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      */
getCallingUid()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      */
clearCallingIdentity()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      */
restoreCallingIdentity(long token)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      */
flushPendingCommands()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      */
joinThreadPool()118     public static final native void joinThreadPool();
119 
120     /**
121      * Default constructor initializes the object.
122      */
Binder()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      */
attachInterface(IInterface owner, String descriptor)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      */
getInterfaceDescriptor()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      */
pingBinder()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      */
isBinderAlive()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      */
queryLocalInterface(String descriptor)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      */
onTransact(int code, Parcel data, Parcel reply, int flags)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      */
dump(FileDescriptor fd, String[] args)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      */
dump(FileDescriptor fd, PrintWriter fout, String[] args)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      */
transact(int code, Parcel data, Parcel reply, int flags)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      */
linkToDeath(DeathRecipient recipient, int flags)258     public void linkToDeath(DeathRecipient recipient, int flags) {
259     }
260 
261     /**
262      * Local implementation is a no-op.
263      */
unlinkToDeath(DeathRecipient recipient, int flags)264     public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
265         return true;
266     }
267 
finalize()268     protected void finalize() throws Throwable {
269         try {
270             destroy();
271         } finally {
272             super.finalize();
273         }
274     }
275 
init()276     private native final void init();
destroy()277     private native final void destroy();
execTransact(int code, int dataObj, int replyObj, int flags)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 
301 final class BinderProxy implements IBinder {
pingBinder()302     public native boolean pingBinder();
isBinderAlive()303     public native boolean isBinderAlive();
304 
queryLocalInterface(String descriptor)305     public IInterface queryLocalInterface(String descriptor) {
306         return null;
307     }
308 
getInterfaceDescriptor()309     public native String getInterfaceDescriptor() throws RemoteException;
transact(int code, Parcel data, Parcel reply, int flags)310     public native boolean transact(int code, Parcel data, Parcel reply,
311             int flags) throws RemoteException;
linkToDeath(DeathRecipient recipient, int flags)312     public native void linkToDeath(DeathRecipient recipient, int flags)
313             throws RemoteException;
unlinkToDeath(DeathRecipient recipient, int flags)314     public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
315 
dump(FileDescriptor fd, String[] args)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 
BinderProxy()327     BinderProxy() {
328         mSelf = new WeakReference(this);
329     }
330 
331     @Override
finalize()332     protected void finalize() throws Throwable {
333         try {
334             destroy();
335         } finally {
336             super.finalize();
337         }
338     }
339 
destroy()340     private native final void destroy();
341 
sendDeathNotice(DeathRecipient recipient)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