package com.lody.virtual.client.hook.patchs.am;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import com.lody.virtual.client.VClientImpl;
import com.lody.virtual.client.env.SpecialComponentList;
import com.lody.virtual.client.hook.base.Hook;
import com.lody.virtual.client.hook.utils.HookUtils;
import com.lody.virtual.client.ipc.VActivityManager;
import com.lody.virtual.helper.utils.VLog;
import com.lody.virtual.os.VUserHandle;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.List;
import java.util.ListIterator;
import java.util.WeakHashMap;
import mirror.android.app.LoadedApk;
import mirror.android.content.IIntentReceiverJB;
/**
* @author Lody
*/
/* package */ class RegisterReceiver extends Hook {
private static final boolean DEBUG = true;
private static final int IDX_IIntentReceiver = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
? 2
: 1;
private static final int IDX_RequiredPermission = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
? 4
: 3;
private static final int IDX_IntentFilter = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
? 3
: 2;
private WeakHashMap<IBinder, IIntentReceiver> mProxyIIntentReceivers = new WeakHashMap<>();
@Override
public String getName() {
return "registerReceiver";
}
@Override
public Object call(Object who, Method method, Object... args) throws Throwable {
HookUtils.replaceFirstAppPkg(args);
args[IDX_RequiredPermission] = null;
IntentFilter filter = (IntentFilter) args[IDX_IntentFilter];
IntentFilter backupFilter = new IntentFilter(filter);
protectIntentFilter(filter);
if (args.length > IDX_IIntentReceiver && IIntentReceiver.class.isInstance(args[IDX_IIntentReceiver])) {
final IInterface old = (IInterface) args[IDX_IIntentReceiver];
if (!IIntentReceiverProxy.class.isInstance(old)) {
final IBinder token = old.asBinder();
if (token != null) {
token.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
token.unlinkToDeath(this, 0);
mProxyIIntentReceivers.remove(token);
}
}, 0);
IIntentReceiver proxyIIntentReceiver = mProxyIIntentReceivers.get(token);
if (proxyIIntentReceiver == null) {
proxyIIntentReceiver = new IIntentReceiverProxy(old);
mProxyIIntentReceivers.put(token, proxyIIntentReceiver);
}
WeakReference mDispatcher = LoadedApk.ReceiverDispatcher.InnerReceiver.mDispatcher.get(old);
if (mDispatcher != null) {
LoadedApk.ReceiverDispatcher.mIIntentReceiver.set(mDispatcher.get(), proxyIIntentReceiver);
args[IDX_IIntentReceiver] = proxyIIntentReceiver;
}
}
}
}
Object res = method.invoke(who, args);
Intent intent = VActivityManager.get().dispatchStickyBroadcast(backupFilter);
if (intent != null) {
return intent;
}
return res;
}
private void protectIntentFilter(IntentFilter filter) {
if (filter != null) {
List<String> actions = mirror.android.content.IntentFilter.mActions.get(filter);
ListIterator<String> iterator = actions.listIterator();
while (iterator.hasNext()) {
String action = iterator.next();
if (SpecialComponentList.isActionInBlackList(action)) {
iterator.remove();
continue;
}
String newAction = SpecialComponentList.protectAction(action);
if (newAction != null) {
if (DEBUG) {
VLog.d("IntentSender", "register=" + newAction);
}
iterator.set(newAction);
}
}
}
}
@Override
public boolean isEnable() {
return isAppProcess();
}
private static class IIntentReceiverProxy extends IIntentReceiver.Stub {
IInterface old;
IIntentReceiverProxy(IInterface old) {
this.old = old;
}
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) throws RemoteException {
if (!accept(intent)) {
return;
}
if (intent.hasExtra("_VA_|_intent_")) {
intent = intent.getParcelableExtra("_VA_|_intent_");
}
SpecialComponentList.unprotectIntent(intent);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
IIntentReceiverJB.performReceive.call(old, intent, resultCode, data, extras, ordered, sticky, sendingUser);
} else {
mirror.android.content.IIntentReceiver.performReceive.call(old, intent, resultCode, data, extras, ordered, sticky);
}
}
private boolean accept(Intent intent) {
int uid = intent.getIntExtra("_VA_|_uid_", -1);
if (uid != -1) {
return VClientImpl.get().getVUid() == uid;
}
int userId = intent.getIntExtra("_VA_|_user_id_", -1);
if (userId != -1) {
return userId == VUserHandle.myUserId();
}
return true;
}
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered,
boolean sticky) throws android.os.RemoteException {
this.performReceive(intent, resultCode, data, extras, ordered, sticky, 0);
}
}
}