package com.tws.plugin.core;
import java.util.Map;
import tws.component.log.TwsLog;
import android.app.Service;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import com.tws.plugin.core.android.HackActivityThread;
import com.tws.plugin.core.android.HackContextImpl;
import com.tws.plugin.manager.PluginManagerHelper;
import com.tws.plugin.util.ProcessUtil;
/**
* 用于拦截Activity Service Receiver的生命周期函数 同时可以跟踪一些其他消息
*
* @author yongchen
*
*/
public class PluginAppTrace implements Handler.Callback {
private static final String TAG = "rick_Print:PluginAppTrace";
private final Handler mHandler;
public PluginAppTrace(Handler handler) {
mHandler = handler;
}
@Override
public boolean handleMessage(Message msg) {
TwsLog.d(TAG, ">>> handling: " + CodeConst.codeToString(msg.what));
Result result = beforeHandle(msg);
try {
mHandler.handleMessage(msg);
TwsLog.d(TAG, ">>> done: " + CodeConst.codeToString(msg.what));
} finally {
afterHandle(msg, result);
}
return true;
}
private Result beforeHandle(Message msg) {
switch (msg.what) {
case CodeConst.LAUNCH_ACTIVITY:
case CodeConst.RELAUNCH_ACTIVITY:
beforeLaunchActivityFor360Safe();
return null;
case CodeConst.RECEIVER:
return beforeReceiver(msg);
case CodeConst.CREATE_SERVICE:
return beforeCreateService(msg);
case CodeConst.STOP_SERVICE:
return beforeStopService(msg);
}
return null;
}
private static void beforeLaunchActivityFor360Safe() {
// 检查mInstrumention是否已经替换成功。
// 之所以要检查,是因为如果手机上安装了360手机卫士等app,它们可能会劫持用户app的ActivityThread对象,
// 导致在PluginApplication的onCreate方法里面替换mInstrumention可能会失败
// 所以这里再做一次检查
PluginInjector.injectInstrumentation();
}
private static Result beforeReceiver(Message msg) {
if (ProcessUtil.isPluginProcess()) {//判断进程是为了提高效率, 因为插件组件都是在插件进程中运行的.
Class clazz = PluginIntentResolver.resolveReceiverForClassLoader(msg.obj);
//找到class说明是插件中定义的receiver
if (clazz != null) {
PluginInjector.hackHostClassLoaderIfNeeded();
Context baseContext = PluginLoader.getApplication().getBaseContext();
Context newBase = PluginLoader.getDefaultPluginContext(clazz);
PluginInjector.replaceReceiverContext(baseContext, newBase);
Result result = new Result();
result.baseContext = baseContext;
return result;
} else {
//宿主的Receiver的context不需要做特别处理,因为在framework中Receiver的context本身是对appliction的包装。
//而宿主的application的baseContext已经在插件框架init的时候替换过了
}
}
return null;
}
private static Result beforeCreateService(Message msg) {
Result result = new Result();
result.serviceName = PluginIntentResolver.resolveServiceForClassLoader(msg.obj);
return result;
}
private static Result beforeStopService(Message msg) {
if (ProcessUtil.isPluginProcess()) {
//销毁service时回收映射关系, 之所以要回收映射关系是为了能在宿主中尽量少的注册占位组件.
//即回收映射关系并不是必须的, 只要预注册的占位组件数据足够即可.
if (HackActivityThread.get() != null) {
Map<IBinder, Service> services = HackActivityThread.get().getServices();
if (services != null) {
Service service = services.get(msg.obj);
if (service != null) {
String pluginServiceClassName = service.getClass().getName();
TwsLog.d(TAG, "beforeStopService unBindStubService:" + pluginServiceClassName);
PluginManagerHelper.unBindStubService(pluginServiceClassName);
}
}
}
}
return null;
}
private static void afterHandle(Message msg, Result result) {
switch (msg.what) {
case CodeConst.RECEIVER:
afterReceiver(result);
break;
case CodeConst.CREATE_SERVICE:
afterCreateService(result);
break;
}
}
private static void afterReceiver(Result result) {
if (ProcessUtil.isPluginProcess()) {
if (result != null && result.baseContext != null) {
new HackContextImpl(result.baseContext).setReceiverRestrictedContext(null);
}
}
}
private static void afterCreateService(Result result) {
//这里不做进程判断,是因为如果是宿主进程, 也需要为宿主service换context
if (result.serviceName.startsWith(PluginIntentResolver.CLASS_PREFIX_SERVICE)) {
//替换service的context
//在引入了PluginShadowService以后,这个已经是多余的了, 注释掉先.
//PluginInjector.replacePluginServiceContext(result.serviceName.replace(PluginIntentResolver.CLASS_PREFIX_SERVICE, ""));
} else {
//给宿主service注入一个无害的BaseContext, 主要是为了重写宿主Service的sentBroadCast和startService方法
//使得在宿主的service中通过intent可以打开插件的组件
PluginInjector.replaceHostServiceContext(result.serviceName);
}
}
static class Result {
String serviceName;
Context baseContext;
}
private static class CodeConst {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING = 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
public static final int REQUEST_THUMBNAIL = 117;
public static final int CONFIGURATION_CHANGED = 118;
public static final int CLEAN_UP_CONTEXT = 119;
public static final int GC_WHEN_IDLE = 120;
public static final int BIND_SERVICE = 121;
public static final int UNBIND_SERVICE = 122;
public static final int DUMP_SERVICE = 123;
public static final int LOW_MEMORY = 124;
public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
public static final int RELAUNCH_ACTIVITY = 126;
public static final int PROFILER_CONTROL = 127;
public static final int CREATE_BACKUP_AGENT = 128;
public static final int DESTROY_BACKUP_AGENT = 129;
public static final int SUICIDE = 130;
public static final int REMOVE_PROVIDER = 131;
public static final int ENABLE_JIT = 132;
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
public static final int SCHEDULE_CRASH = 134;
public static final int DUMP_HEAP = 135;
public static final int DUMP_ACTIVITY = 136;
public static final int SLEEPING = 137;
public static final int SET_CORE_SETTINGS = 138;
public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
public static final int TRIM_MEMORY = 140;
public static final int DUMP_PROVIDER = 141;
public static final int UNSTABLE_PROVIDER_DIED = 142;
public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
public static final int INSTALL_PROVIDER = 145;
public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
public static final int CANCEL_VISIBLE_BEHIND = 147;
public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
public static final int ENTER_ANIMATION_COMPLETE = 149;
public static String codeToString(int code) {
switch (code) {
case LAUNCH_ACTIVITY:
return "LAUNCH_ACTIVITY";
case PAUSE_ACTIVITY:
return "PAUSE_ACTIVITY";
case PAUSE_ACTIVITY_FINISHING:
return "PAUSE_ACTIVITY_FINISHING";
case STOP_ACTIVITY_SHOW:
return "STOP_ACTIVITY_SHOW";
case STOP_ACTIVITY_HIDE:
return "STOP_ACTIVITY_HIDE";
case SHOW_WINDOW:
return "SHOW_WINDOW";
case HIDE_WINDOW:
return "HIDE_WINDOW";
case RESUME_ACTIVITY:
return "RESUME_ACTIVITY";
case SEND_RESULT:
return "SEND_RESULT";
case DESTROY_ACTIVITY:
return "DESTROY_ACTIVITY";
case BIND_APPLICATION:
return "BIND_APPLICATION";
case EXIT_APPLICATION:
return "EXIT_APPLICATION";
case NEW_INTENT:
return "NEW_INTENT";
case RECEIVER:
return "RECEIVER";
case CREATE_SERVICE:
return "CREATE_SERVICE";
case SERVICE_ARGS:
return "SERVICE_ARGS";
case STOP_SERVICE:
return "STOP_SERVICE";
case REQUEST_THUMBNAIL:
return "REQUEST_THUMBNAIL";
case CONFIGURATION_CHANGED:
return "CONFIGURATION_CHANGED";
case CLEAN_UP_CONTEXT:
return "CLEAN_UP_CONTEXT";
case GC_WHEN_IDLE:
return "GC_WHEN_IDLE";
case BIND_SERVICE:
return "BIND_SERVICE";
case UNBIND_SERVICE:
return "UNBIND_SERVICE";
case DUMP_SERVICE:
return "DUMP_SERVICE";
case LOW_MEMORY:
return "LOW_MEMORY";
case ACTIVITY_CONFIGURATION_CHANGED:
return "ACTIVITY_CONFIGURATION_CHANGED";
case RELAUNCH_ACTIVITY:
return "RELAUNCH_ACTIVITY";
case PROFILER_CONTROL:
return "PROFILER_CONTROL";
case CREATE_BACKUP_AGENT:
return "CREATE_BACKUP_AGENT";
case DESTROY_BACKUP_AGENT:
return "DESTROY_BACKUP_AGENT";
case SUICIDE:
return "SUICIDE";
case REMOVE_PROVIDER:
return "REMOVE_PROVIDER";
case ENABLE_JIT:
return "ENABLE_JIT";
case DISPATCH_PACKAGE_BROADCAST:
return "DISPATCH_PACKAGE_BROADCAST";
case SCHEDULE_CRASH:
return "SCHEDULE_CRASH";
case DUMP_HEAP:
return "DUMP_HEAP";
case DUMP_ACTIVITY:
return "DUMP_ACTIVITY";
case SLEEPING:
return "SLEEPING";
case SET_CORE_SETTINGS:
return "SET_CORE_SETTINGS";
case UPDATE_PACKAGE_COMPATIBILITY_INFO:
return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
case TRIM_MEMORY:
return "TRIM_MEMORY";
case DUMP_PROVIDER:
return "DUMP_PROVIDER";
case UNSTABLE_PROVIDER_DIED:
return "UNSTABLE_PROVIDER_DIED";
case REQUEST_ASSIST_CONTEXT_EXTRAS:
return "REQUEST_ASSIST_CONTEXT_EXTRAS";
case TRANSLUCENT_CONVERSION_COMPLETE:
return "TRANSLUCENT_CONVERSION_COMPLETE";
case INSTALL_PROVIDER:
return "INSTALL_PROVIDER";
case ON_NEW_ACTIVITY_OPTIONS:
return "ON_NEW_ACTIVITY_OPTIONS";
case CANCEL_VISIBLE_BEHIND:
return "CANCEL_VISIBLE_BEHIND";
case BACKGROUND_VISIBLE_BEHIND_CHANGED:
return "BACKGROUND_VISIBLE_BEHIND_CHANGED";
case ENTER_ANIMATION_COMPLETE:
return "ENTER_ANIMATION_COMPLETE";
}
return "(unknown: " + code +")";
}
}
}