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); } } }