package com.lody.virtual.client.hook.base; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; import com.lody.virtual.client.core.VirtualCore; import java.io.FileDescriptor; import java.lang.reflect.Method; import mirror.RefStaticMethod; import mirror.android.os.ServiceManager; /** * @author Lody */ @SuppressWarnings("unchecked") public class BinderInvocationStub extends MethodInvocationStub<IInterface> implements IBinder { private static final String TAG = BinderInvocationStub.class.getSimpleName(); private IBinder mBaseBinder; public BinderInvocationStub(RefStaticMethod<IInterface> asInterfaceMethod, IBinder binder) { this(asInterface(asInterfaceMethod, binder)); } 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(RefStaticMethod<IInterface> asInterfaceMethod, IBinder binder) { if (asInterfaceMethod == null || binder == null) { return null; } return asInterfaceMethod.call(binder); } 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) { Log.d(TAG, "Could not create stub " + stubClass.getName() + ". Cause: " + e); return null; } } public void replaceService(String name) { if (mBaseBinder != null) { ServiceManager.sCache.get().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(); } public Context getContext() { return VirtualCore.get().getContext(); } @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; } }