content: package cn.thens.okbinder2;
  
  import android.os.Binder;
  import android.os.IBinder;
  
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  
  final class ReflectionFactory implements OkBinderFactory {
      @Override
      public Binder newBinder(Class<?> serviceClass, Object remoteObject) {
          return new MyBinder(remoteObject, serviceClass);
      }
  
      @Override
      public Object newProxy(final Class<?> serviceClass, final IBinder binder) {
          final ClassLoader classLoader = serviceClass.getClassLoader();
          return serviceClass.cast(Proxy.newProxyInstance(classLoader, new Class[]{serviceClass},
                  new MyProxy(binder, serviceClass)));
      }
  
      private static final class MethodFunction implements Function {
          private final Method method;
  
          private MethodFunction(Method method) {
              this.method = method;
          }
  
          @Override
          public Object invoke(Object obj, Object[] args) throws Throwable {
              try {
                  return method.invoke(obj, args);
              } catch (InvocationTargetException e) {
                  Throwable cause = e.getCause();
                  throw cause != null ? cause : e;
              }
          }
      }
  
      private static final class MyBinder extends BaseBinder {
          public MyBinder(Object remoteObject, Class<?> serviceClass) {
              super(serviceClass, remoteObject);
              for (Method method : serviceClass.getMethods()) {
                  if (method.isBridge()) continue;
                  register(OkBinder.getFunctionId(method), new MethodFunction(method));
              }
          }
      }
  
      private static final class MyProxy extends BaseProxy implements InvocationHandler {
          public MyProxy(IBinder binder, Class<?> serviceClass) {
              super(serviceClass, binder);
          }
  
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) {
              int flags = isOneWay(method) ? IBinder.FLAG_ONEWAY : 0;
              return transact(flags, OkBinder.getFunctionId(method), args);
          }
      }
  
      private static boolean isOneWay(Method method) {
          return method.getReturnType() == Void.TYPE;
      }
  }
  