package cm.android.hook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import android.annotation.TargetApi; import android.os.Build; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.RemoteException; import java.io.FileDescriptor; import java.lang.reflect.Method; @SuppressWarnings("unchecked") public class BinderInvocationStub extends MethodInvocationStub<IInterface> implements IBinder { private static Logger logger = LoggerFactory.getLogger("BinderInvocationStub"); private static final String TAG = BinderInvocationStub.class.getSimpleName(); private IBinder mBaseBinder; public BinderInvocationStub(Class<?> stubClass, IBinder binder) { this(asInterface(stubClass, binder)); } public BinderInvocationStub(IInterface mBaseInterface) { super(mBaseInterface); mBaseBinder = getBaseInterface() != null ? getBaseInterface().asBinder() : null; addMethodProxy(new AsBinder()); } private static IInterface asInterface(Class<?> stubClass, IBinder binder) { try { if (stubClass == null || binder == null) { return null; } Method asInterface = stubClass.getMethod("asInterface", IBinder.class); return (IInterface) asInterface.invoke(null, binder); } catch (Exception e) { logger.error("Could not create stub {}, cause {}", stubClass.getName(), e); return null; } } public void replaceService(String name) { if (mBaseBinder != null) { HookHelper.getsCache().put(name, this); } } private final class AsBinder extends MethodProxy { @Override public String getMethodName() { return "asBinder"; } @Override public Object call(Object who, Method method, Object... args) throws Throwable { return BinderInvocationStub.this; } } @Override public String getInterfaceDescriptor() throws RemoteException { return mBaseBinder.getInterfaceDescriptor(); } @Override public boolean pingBinder() { return mBaseBinder.pingBinder(); } @Override public boolean isBinderAlive() { return mBaseBinder.isBinderAlive(); } @Override public IInterface queryLocalInterface(String descriptor) { return getProxyInterface(); } @Override public void dump(FileDescriptor fd, String[] args) throws RemoteException { mBaseBinder.dump(fd, args); } @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) @Override public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException { mBaseBinder.dumpAsync(fd, args); } @Override public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { return mBaseBinder.transact(code, data, reply, flags); } @Override public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException { mBaseBinder.linkToDeath(recipient, flags); } @Override public boolean unlinkToDeath(DeathRecipient recipient, int flags) { return mBaseBinder.unlinkToDeath(recipient, flags); } public IBinder getBaseBinder() { return mBaseBinder; } }