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