Merge pull request #179 from ElderDrivers/sandhook

Sandhook
This commit is contained in:
ganyao114 2019-03-22 15:11:38 +08:00 committed by GitHub
commit 8c437cdbf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 147 additions and 84 deletions

View File

@ -471,8 +471,23 @@ public final class DexMaker {
} }
} }
public ClassLoader loadClassDirect(ClassLoader parent, File dexCache, String dexFileName) {
File result = new File(dexCache, dexFileName);
// Check that the file exists. If it does, return a DexClassLoader and skip all
// the dex bytecode generation.
if (result.exists()) {
return generateClassLoader(result, dexCache, parent);
} else {
return null;
}
}
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException { public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException {
return generateAndLoad(parent, dexCache, null); return generateAndLoad(parent, dexCache, generateFileName(), false);
}
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String dexFileName) throws IOException {
return generateAndLoad(parent, dexCache, dexFileName, false);
} }
/** /**
@ -500,9 +515,8 @@ public final class DexMaker {
* @param dexCache the destination directory where generated and optimized * @param dexCache the destination directory where generated and optimized
* dex files will be written. If null, this class will try to guess the * dex files will be written. If null, this class will try to guess the
* application's private data dir. * application's private data dir.
* @param fileName the name of dex file
*/ */
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String fileName) throws IOException { public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String dexFileName, boolean deleteOld) throws IOException {
if (dexCache == null) { if (dexCache == null) {
String property = System.getProperty("dexmaker.dexcache"); String property = System.getProperty("dexmaker.dexcache");
if (property != null) { if (property != null) {
@ -516,14 +530,18 @@ public final class DexMaker {
} }
} }
if (fileName == null || fileName.isEmpty()) File result = new File(dexCache, dexFileName);
fileName = generateFileName();
File result = new File(dexCache, fileName);
// Check that the file exists. If it does, return a DexClassLoader and skip all
// the dex bytecode generation.
if (result.exists()) { if (result.exists()) {
if (deleteOld) {
try {
deleteOldDex(result);
} catch (Throwable throwable) {
}
} else {
return generateClassLoader(result, dexCache, parent); return generateClassLoader(result, dexCache, parent);
} }
}
/* /*
* This implementation currently dumps the dex to the filesystem. It * This implementation currently dumps the dex to the filesystem. It
@ -532,7 +550,14 @@ public final class DexMaker {
* *
* TODO: load the dex from memory where supported. * TODO: load the dex from memory where supported.
*/ */
File parentDir = result.getParentFile();
if (!parentDir.exists()) {
parentDir.mkdirs();
}
result.createNewFile(); result.createNewFile();
JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result)); JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result));
JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME); JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME);
byte[] dex = generate(); byte[] dex = generate();
@ -544,6 +569,32 @@ public final class DexMaker {
return generateClassLoader(result, dexCache, parent); return generateClassLoader(result, dexCache, parent);
} }
public void deleteOldDex(File dexFile) {
dexFile.delete();
String dexDir = dexFile.getParent();
File oatDir = new File(dexDir, "/oat/");
File oatDirArm = new File(oatDir, "/arm/");
File oatDirArm64 = new File(oatDir, "/arm64/");
if (!oatDir.exists())
return;
String nameStart = dexFile.getName().replaceAll(".jar", "");
doDeleteOatFiles(oatDir, nameStart);
doDeleteOatFiles(oatDirArm, nameStart);
doDeleteOatFiles(oatDirArm64, nameStart);
}
private void doDeleteOatFiles(File dir, String nameStart) {
if (!dir.exists())
return;
File[] oats = dir.listFiles();
if (oats == null)
return;
for (File oatFile:oats) {
if (oatFile.isFile() && oatFile.getName().startsWith(nameStart))
oatFile.delete();
}
}
DexFile getDexFile() { DexFile getDexFile() {
if (outputDex == null) { if (outputDex == null) {
DexOptions options = new DexOptions(); DexOptions options = new DexOptions();

View File

@ -24,7 +24,7 @@ dependencies {
compileOnly files("libs/framework-stub.jar") compileOnly files("libs/framework-stub.jar")
implementation project(':edxp-common') implementation project(':edxp-common')
implementation project(':xposed-bridge') implementation project(':xposed-bridge')
implementation 'com.swift.sandhook:hooklib:3.2.2' implementation 'com.swift.sandhook:hooklib:3.2.8'
compileOnly project(':dexmaker') compileOnly project(':dexmaker')
} }

View File

@ -4,7 +4,6 @@ import android.app.AndroidAppHelper;
import android.text.TextUtils; import android.text.TextUtils;
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
import com.elderdrivers.riru.edxp.util.Utils;
import com.elderdrivers.riru.edxp.sandhook.config.SandHookEdxpConfig; import com.elderdrivers.riru.edxp.sandhook.config.SandHookEdxpConfig;
import com.elderdrivers.riru.edxp.sandhook.config.SandHookProvider; import com.elderdrivers.riru.edxp.sandhook.config.SandHookProvider;
import com.elderdrivers.riru.edxp.sandhook.core.HookMain; import com.elderdrivers.riru.edxp.sandhook.core.HookMain;
@ -14,9 +13,9 @@ import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysBootstrapHookInfo;
import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysInnerHookInfo; import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysInnerHookInfo;
import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.WorkAroundHookInfo; import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.WorkAroundHookInfo;
import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker; import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker;
import com.elderdrivers.riru.edxp.util.Utils;
import com.swift.sandhook.SandHookConfig; import com.swift.sandhook.SandHookConfig;
import com.swift.sandhook.xposedcompat.XposedCompat; import com.swift.sandhook.xposedcompat.XposedCompat;
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -31,6 +30,12 @@ public class Router {
private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false);
static boolean useSandHook;
static {
useSandHook = EdXpConfigGlobal.getHookProvider() instanceof SandHookProvider;
}
public static void prepare(boolean isSystem) { public static void prepare(boolean isSystem) {
// this flag is needed when loadModules // this flag is needed when loadModules
@ -81,34 +86,47 @@ public class Router {
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);
ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER; ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER;
if (isSystem) { if (isSystem) {
HookMain.doHookDefault( if (useSandHook) {
Router.class.getClassLoader(),
classLoader,
SysBootstrapHookInfo.class.getName());
XposedCompat.addHookers(classLoader, SysBootstrapHookInfo.hookItems); XposedCompat.addHookers(classLoader, SysBootstrapHookInfo.hookItems);
} else { } else {
HookMain.doHookDefault( HookMain.doHookDefault(
Router.class.getClassLoader(), Router.class.getClassLoader(),
classLoader, classLoader,
AppBootstrapHookInfo.class.getName()); SysBootstrapHookInfo.class.getName());
}
} else {
if (useSandHook) {
XposedCompat.addHookers(classLoader, AppBootstrapHookInfo.hookItems); XposedCompat.addHookers(classLoader, AppBootstrapHookInfo.hookItems);
} else {
HookMain.doHookDefault(
Router.class.getClassLoader(),
classLoader,
AppBootstrapHookInfo.class.getName());
}
} }
} }
public static void startSystemServerHook() { public static void startSystemServerHook() {
// HookMain.doHookDefault( if (useSandHook) {
// Router.class.getClassLoader(),
// SystemMainHooker.systemServerCL,
// SysInnerHookInfo.class.getName());
XposedCompat.addHookers(SystemMainHooker.systemServerCL, SysInnerHookInfo.hookItems); XposedCompat.addHookers(SystemMainHooker.systemServerCL, SysInnerHookInfo.hookItems);
} else {
HookMain.doHookDefault(
Router.class.getClassLoader(),
SystemMainHooker.systemServerCL,
SysInnerHookInfo.class.getName());
}
} }
public static void startWorkAroundHook() { public static void startWorkAroundHook() {
if (useSandHook) {
XposedCompat.addHookers(XposedBridge.BOOTCLASSLOADER, WorkAroundHookInfo.hookItems);
} else {
HookMain.doHookDefault( HookMain.doHookDefault(
Router.class.getClassLoader(), Router.class.getClassLoader(),
XposedBridge.BOOTCLASSLOADER, XposedBridge.BOOTCLASSLOADER,
WorkAroundHookInfo.class.getName()); WorkAroundHookInfo.class.getName());
} }
}
public static void onEnterChildProcess() { public static void onEnterChildProcess() {
forkCompleted = true; forkCompleted = true;

View File

@ -7,11 +7,14 @@ import com.elderdrivers.riru.edxp.sandhook.entry.hooker.OnePlusWorkAroundHooker;
public class AppBootstrapHookInfo implements KeepMembers { public class AppBootstrapHookInfo implements KeepMembers {
public static String[] hookItemNames = { public static String[] hookItemNames = {
OnePlusWorkAroundHooker.class.getName() OnePlusWorkAroundHooker.class.getName(),
HandleBindAppHooker.class.getName(),
LoadedApkConstructorHooker.class.getName(),
}; };
public static Class[] hookItems = { public static Class[] hookItems = {
HandleBindAppHooker.class, HandleBindAppHooker.class,
LoadedApkConstructorHooker.class LoadedApkConstructorHooker.class,
OnePlusWorkAroundHooker.class
}; };
} }

View File

@ -8,12 +8,16 @@ import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker;
public class SysBootstrapHookInfo implements KeepMembers { public class SysBootstrapHookInfo implements KeepMembers {
public static String[] hookItemNames = { public static String[] hookItemNames = {
OnePlusWorkAroundHooker.class.getName() OnePlusWorkAroundHooker.class.getName(),
HandleBindAppHooker.class.getName(),
SystemMainHooker.class.getName(),
LoadedApkConstructorHooker.class.getName()
}; };
public static Class[] hookItems = { public static Class[] hookItems = {
HandleBindAppHooker.class, HandleBindAppHooker.class,
SystemMainHooker.class, SystemMainHooker.class,
LoadedApkConstructorHooker.class LoadedApkConstructorHooker.class,
OnePlusWorkAroundHooker.class
}; };
} }

View File

@ -9,5 +9,6 @@ public class WorkAroundHookInfo implements KeepMembers {
}; };
public static Class[] hookItems = { public static Class[] hookItems = {
OnePlusWorkAroundHooker.class
}; };
} }

View File

@ -7,14 +7,13 @@ import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo; import android.content.res.CompatibilityInfo;
import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.common.KeepMembers;
import com.elderdrivers.riru.edxp.util.Utils;
import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.Main;
import com.elderdrivers.riru.edxp.sandhook.entry.Router; import com.elderdrivers.riru.edxp.sandhook.entry.Router;
import com.elderdrivers.riru.edxp.util.Utils;
import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHook;
import com.swift.sandhook.annotation.HookClass; import com.swift.sandhook.annotation.HookClass;
import com.swift.sandhook.annotation.HookMethod; import com.swift.sandhook.annotation.HookMethod;
import com.swift.sandhook.annotation.HookMethodBackup; import com.swift.sandhook.annotation.HookMethodBackup;
import com.swift.sandhook.annotation.HookMode;
import com.swift.sandhook.annotation.Param; import com.swift.sandhook.annotation.Param;
import com.swift.sandhook.annotation.SkipParamCheck; import com.swift.sandhook.annotation.SkipParamCheck;
import com.swift.sandhook.annotation.ThisObject; import com.swift.sandhook.annotation.ThisObject;
@ -27,8 +26,8 @@ import de.robv.android.xposed.XposedInit;
import de.robv.android.xposed.callbacks.XC_LoadPackage; import de.robv.android.xposed.callbacks.XC_LoadPackage;
import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_PACKAGE_NAME; import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_PACKAGE_NAME;
import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader;
import static com.elderdrivers.riru.edxp.sandhook.entry.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME; import static com.elderdrivers.riru.edxp.sandhook.entry.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader;
// normal process initialization (for new Activity, Service, BroadcastReceiver etc.) // normal process initialization (for new Activity, Service, BroadcastReceiver etc.)
@HookClass(ActivityThread.class) @HookClass(ActivityThread.class)
@ -45,7 +44,7 @@ public class HandleBindAppHooker implements KeepMembers {
@HookMethod("handleBindApplication") @HookMethod("handleBindApplication")
public static void hook(@ThisObject ActivityThread thiz, @Param("android.app.ActivityThread$AppBindData") Object bindData) throws Throwable { public static void hook(@ThisObject ActivityThread thiz, @Param("android.app.ActivityThread$AppBindData") Object bindData) throws Throwable {
if (XposedBlackListHooker.shouldDisableHooks("")) { if (XposedBlackListHooker.shouldDisableHooks("")) {
SandHook.callOriginByBackup(backup, thiz, bindData); backup(thiz, bindData);
return; return;
} }
try { try {
@ -96,10 +95,11 @@ public class HandleBindAppHooker implements KeepMembers {
} catch (Throwable t) { } catch (Throwable t) {
Router.logE("error when hooking bindApp", t); Router.logE("error when hooking bindApp", t);
} finally { } finally {
SandHook.callOriginByBackup(backup, thiz, bindData); backup(thiz, bindData);
} }
} }
public static void backup(Object thiz, Object bindData) { public static void backup(Object thiz, Object bindData) throws Throwable {
SandHook.callOriginByBackup(backup, thiz, bindData);
} }
} }

View File

@ -47,13 +47,12 @@ public class LoadedApkConstructorHooker implements KeepMembers {
boolean includeCode, boolean registerPackage) throws Throwable { boolean includeCode, boolean registerPackage) throws Throwable {
if (XposedBlackListHooker.shouldDisableHooks("")) { if (XposedBlackListHooker.shouldDisableHooks("")) {
SandHook.callOriginByBackup(backup, thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage); backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage);
return; return;
} }
Router.logD("LoadedApk#<init> starts"); Router.logD("LoadedApk#<init> starts");
SandHook.callOriginByBackup(backup, thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage); backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage);
try { try {
LoadedApk loadedApk = (LoadedApk) thiz; LoadedApk loadedApk = (LoadedApk) thiz;
@ -105,7 +104,7 @@ public class LoadedApkConstructorHooker implements KeepMembers {
public static void backup(Object thiz, ActivityThread activityThread, public static void backup(Object thiz, ActivityThread activityThread,
ApplicationInfo aInfo, CompatibilityInfo compatInfo, ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, ClassLoader baseLoader, boolean securityViolation,
boolean includeCode, boolean registerPackage) { boolean includeCode, boolean registerPackage) throws Throwable {
SandHook.callOriginByBackup(backup, thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage);
} }
} }

View File

@ -3,6 +3,7 @@ package com.elderdrivers.riru.edxp.sandhook.entry.hooker;
import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.common.KeepMembers;
import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.Main;
import com.elderdrivers.riru.edxp.sandhook.entry.Router; import com.elderdrivers.riru.edxp.sandhook.entry.Router;
import com.swift.sandhook.SandHook;
import com.swift.sandhook.annotation.HookClass; import com.swift.sandhook.annotation.HookClass;
import com.swift.sandhook.annotation.HookMethod; import com.swift.sandhook.annotation.HookMethod;
import com.swift.sandhook.annotation.HookMethodBackup; import com.swift.sandhook.annotation.HookMethodBackup;
@ -40,7 +41,7 @@ public class OnePlusWorkAroundHooker implements KeepMembers {
static Method backup; static Method backup;
@HookMethod("inCompatConfigList") @HookMethod("inCompatConfigList")
public static boolean hook(int type, String packageName) { public static boolean hook(int type, String packageName) throws Throwable {
if (XposedBridge.disableHooks || Router.forkCompleted) { if (XposedBridge.disableHooks || Router.forkCompleted) {
return backup(type, packageName); return backup(type, packageName);
} }
@ -48,7 +49,7 @@ public class OnePlusWorkAroundHooker implements KeepMembers {
return false; return false;
} }
public static boolean backup(int type, String packageName) { public static boolean backup(int type, String packageName) throws Throwable {
return false; return (boolean) SandHook.callOriginByBackup(backup, null, type, packageName);
} }
} }

View File

@ -38,7 +38,7 @@ public class StartBootstrapServicesHooker implements KeepMembers {
public static void hook(@ThisObject Object systemServer) throws Throwable { public static void hook(@ThisObject Object systemServer) throws Throwable {
if (XposedBridge.disableHooks) { if (XposedBridge.disableHooks) {
SandHook.callOriginByBackup(backup, systemServer); backup(systemServer);
return; return;
} }
@ -71,11 +71,11 @@ public class StartBootstrapServicesHooker implements KeepMembers {
} catch (Throwable t) { } catch (Throwable t) {
Router.logE("error when hooking startBootstrapServices", t); Router.logE("error when hooking startBootstrapServices", t);
} finally { } finally {
backup(systemServer);
}
}
public static void backup(Object systemServer) throws Throwable {
SandHook.callOriginByBackup(backup, systemServer); SandHook.callOriginByBackup(backup, systemServer);
} }
}
public static void backup(Object systemServer) {
}
} }

View File

@ -33,10 +33,10 @@ public class SystemMainHooker implements KeepMembers {
@HookMethod("systemMain") @HookMethod("systemMain")
public static ActivityThread hook() throws Throwable { public static ActivityThread hook() throws Throwable {
if (XposedBridge.disableHooks) { if (XposedBridge.disableHooks) {
return (ActivityThread) SandHook.callOriginByBackup(backup, null); return backup();
} }
Router.logD("ActivityThread#systemMain() starts"); Router.logD("ActivityThread#systemMain() starts");
ActivityThread activityThread = (ActivityThread) SandHook.callOriginByBackup(backup, null); ActivityThread activityThread = backup();
try { try {
// get system_server classLoader // get system_server classLoader
systemServerCL = Thread.currentThread().getContextClassLoader(); systemServerCL = Thread.currentThread().getContextClassLoader();
@ -49,7 +49,7 @@ public class SystemMainHooker implements KeepMembers {
return activityThread; return activityThread;
} }
public static ActivityThread backup() { public static ActivityThread backup() throws Throwable {
return null; return (ActivityThread) SandHook.callOriginByBackup(backup, null);
} }
} }

View File

@ -190,7 +190,7 @@ public class HookerDexMaker implements HookMaker {
HookWrapper.HookEntity hookEntity = null; HookWrapper.HookEntity hookEntity = null;
//try load cache first //try load cache first
try { try {
ClassLoader loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName); ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(mDexDirPath), dexName);
if (loader != null) { if (loader != null) {
hookEntity = loadHookerClass(loader, className); hookEntity = loadHookerClass(loader, className);
} }
@ -222,7 +222,7 @@ public class HookerDexMaker implements HookMaker {
} }
// Create the dex file and load it. // Create the dex file and load it.
try { try {
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName); loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName, true);
} catch (IOException e) { } catch (IOException e) {
//can not write file //can not write file
byte[] dexBytes = mDexMaker.generate(); byte[] dexBytes = mDexMaker.generate();

View File

@ -150,7 +150,7 @@ public class HookerDexMakerNew implements HookMaker {
HookWrapper.HookEntity hookEntity = null; HookWrapper.HookEntity hookEntity = null;
//try load cache first //try load cache first
try { try {
ClassLoader loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName); ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(mDexDirPath), dexName);
if (loader != null) { if (loader != null) {
hookEntity = loadHookerClass(loader, className); hookEntity = loadHookerClass(loader, className);
} }
@ -176,7 +176,7 @@ public class HookerDexMakerNew implements HookMaker {
} }
// Create the dex file and load it. // Create the dex file and load it.
try { try {
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName); loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName, true);
} catch (IOException e) { } catch (IOException e) {
//can not write file //can not write file
byte[] dexBytes = mDexMaker.generate(); byte[] dexBytes = mDexMaker.generate();

View File

@ -9,14 +9,10 @@ public class DexLog {
public static final String TAG = "SandXposed"; public static final String TAG = "SandXposed";
public static volatile boolean DEBUG = true; public static volatile boolean DEBUG = false;
public static int v(String s) { public static int v(String s) {
if (DEBUG) {
return Log.v(TAG, s); return Log.v(TAG, s);
} else {
return 0;
}
} }
public static int i(String s) { public static int i(String s) {
@ -24,7 +20,11 @@ public class DexLog {
} }
public static int d(String s) { public static int d(String s) {
if (DEBUG) {
return Log.d(TAG, s); return Log.d(TAG, s);
} else {
return 0;
}
} }
public static void printMethodHookIn(Member member) { public static void printMethodHookIn(Member member) {
@ -34,33 +34,19 @@ public class DexLog {
} }
public static void printCallOriginError(Member member) { public static void printCallOriginError(Member member) {
if (DEBUG && member != null) { Log.e("SandHook", "method <" + member.toString() + "> call origin error!");
Log.d("SandHook", "method <" + member.toString() + "> call origin error!");
}
} }
public static int w(String s) { public static int w(String s) {
if (DEBUG) {
return Log.w(TAG, s); return Log.w(TAG, s);
} else {
return 0;
}
} }
public static int e(String s) { public static int e(String s) {
if (DEBUG) {
return Log.e(TAG, s); return Log.e(TAG, s);
} else {
return 0;
}
} }
public static int e(String s, Throwable t) { public static int e(String s, Throwable t) {
if (DEBUG) {
return Log.e(TAG, s, t); return Log.e(TAG, s, t);
} else {
return 0;
}
} }