package com.lody.virtual.client.hook.secondary;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import java.io.FileDescriptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
/**
* @author Lody
*/
abstract class StubBinder implements IBinder {
private ClassLoader mClassLoader;
private IBinder mBase;
private IInterface mInterface;
StubBinder(ClassLoader classLoader, IBinder base) {
this.mClassLoader = classLoader;
this.mBase = base;
}
@Override
public String getInterfaceDescriptor() throws RemoteException {
return mBase.getInterfaceDescriptor();
}
@Override
public boolean pingBinder() {
return mBase.pingBinder();
}
@Override
public boolean isBinderAlive() {
return mBase.isBinderAlive();
}
/**
* Anti the Proguard.
*
* Search the AidlClass.Stub.asInterface(IBinder) method by the StackTrace.
*
*/
@Override
public IInterface queryLocalInterface(String descriptor) {
if (mInterface == null) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if (stackTrace == null || stackTrace.length <= 1) {
return null;
}
Class<?> aidlType = null;
IInterface targetInterface = null;
for (StackTraceElement element : stackTrace) {
if (element.isNativeMethod()) {
continue;
}
try {
Method method = mClassLoader.loadClass(element.getClassName())
.getDeclaredMethod(element.getMethodName(), IBinder.class);
if ((method.getModifiers() & Modifier.STATIC) != 0) {
method.setAccessible(true);
Class<?> returnType = method.getReturnType();
if (returnType.isInterface() && IInterface.class.isAssignableFrom(returnType)) {
aidlType = returnType;
targetInterface = (IInterface) method.invoke(null, mBase);
}
}
} catch (Exception e) {
// go to the next cycle
}
}
if (aidlType == null || targetInterface == null) {
return null;
}
InvocationHandler handler = createHandler(aidlType, targetInterface);
mInterface = (IInterface) Proxy.newProxyInstance(mClassLoader, new Class[]{aidlType}, handler);
}
return mInterface;
}
public abstract InvocationHandler createHandler(Class<?> interfaceClass, IInterface iInterface);
@Override
public void dump(FileDescriptor fd, String[] args) throws RemoteException {
mBase.dump(fd, args);
}
@Override
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
mBase.dumpAsync(fd, args);
}
@Override
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
return mBase.transact(code, data, reply, flags);
}
@Override
public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException {
mBase.linkToDeath(recipient, flags);
}
@Override
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return mBase.unlinkToDeath(recipient, flags);
}
}