diff --git a/app/build.gradle b/app/build.gradle index 68529b9735..5d86f695bb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,6 +6,7 @@ import java.text.SimpleDateFormat apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' apply from: rootProject.file('gradle/bytex/bytex.gradle') @@ -214,6 +215,15 @@ dependencies { // releaseImplementation rootProject.ext.dependencies.releaseleakcanary implementation rootProject.ext.dependencies.android_start_up implementation rootProject.ext.dependencies.lancetx_runtime + implementation rootProject.ext.dependencies.lancetx_compiler_lib + kapt rootProject.ext.dependencies.lancetx_compiler + + annotationProcessor rootProject.ext.dependencies.lancetx_compiler + annotationProcessor rootProject.ext.dependencies.google_auto_service + kapt rootProject.ext.dependencies.google_auto_service + compileOnly rootProject.ext.dependencies.google_auto_service + + // implementation rootProject.ext.dependencies.mogocustommap implementation project(':libraries:mapmodule') diff --git a/app/matrixTrace/blackMethodList.txt b/app/matrixTrace/blackMethodList.txt index 502b68e02b..d886ef8e3c 100644 --- a/app/matrixTrace/blackMethodList.txt +++ b/app/matrixTrace/blackMethodList.txt @@ -1,6 +1,10 @@ [package] -keeppackage com/mogo/thread/opt/core/ -keeppackage com/mogo/eagle/core/function/main/threadopt/ +-keeppackage com/knightboost/lancet/api/synchronized_lock/ +-keeppackage com/mogo/core/lancetx/compiler/lib +-keeppackage com/mogo/eagle/core/lancetx/generated/ +-keeppackage com/mogo/launcher/lancet/jank/spi/ -keeppackage com/mogo/launcher -keeppackage com/rousetime/android_startup/ -keeppackage com/mogo/systrace/ diff --git a/app/src/main/java/com/mogo/launcher/lancet/ANRFix.kt b/app/src/main/java/com/mogo/launcher/lancet/ANRFix.kt deleted file mode 100644 index 63ddc771a6..0000000000 --- a/app/src/main/java/com/mogo/launcher/lancet/ANRFix.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.mogo.launcher.lancet - -import android.app.Activity -import android.os.* -import android.view.View -import androidx.annotation.* -import com.knightboost.lancet.api.* -import com.knightboost.lancet.api.Scope.ALL -import com.knightboost.lancet.api.annotations.* -import com.knightboost.lancet.api.annotations.Weaver -import com.mogo.eagle.core.utilcode.util.* -import kotlinx.coroutines.* -import kotlinx.coroutines.Runnable - -@Keep -@Weaver -@Group("anr_fix") -class ANRFix { - - companion object { - -// @JvmStatic -// @TargetClass(value = "android.os.Handler", scope = ALL) -// @TargetMethod(methodName = "post") -// @ReplaceInvoke -// fun handlerPostProxy(handler: Handler, action: Runnable): Boolean { -// if (Looper.getMainLooper() != handler.looper) { -// return handler.post(action) -// } -// val what = ObjectHashCodeUtils.getHashCodeIfNeed(action) -// handler.removeMessages(what) -// val msg = Message.obtain(handler, action) -// msg.what = what -// return handler.sendMessage(msg) -// } -// -// @JvmStatic -// @TargetClass(value = "android.os.Handler", scope = ALL) -// @TargetMethod(methodName = "postDelayed") -// @ReplaceInvoke -// fun handlerPostDelayProxy(handler: Handler, action: Runnable, delayMillis: Long): Boolean { -// if (Looper.getMainLooper() != handler.looper) { -// return handler.postDelayed(action, delayMillis) -// } -// val what = ObjectHashCodeUtils.getHashCodeIfNeed(action) -// handler.removeMessages(what) -// val msg = Message.obtain(handler, action) -// msg.what = what -// return handler.sendMessageDelayed(msg, delayMillis) -// } -// -// @JvmStatic -// @TargetClass(value = "android.app.Activity", scope = ALL) -// @TargetMethod(methodName = "post") -// @ReplaceInvoke -// fun runOnUiThreadOfActivityProxy(activity: Activity, action: Runnable) { -// if (Looper.myLooper() != Looper.getMainLooper()) { -// UiThreadHandler.post(action) -// } else { -// activity.runOnUiThread(action) -// } -// } -// -// @JvmStatic -// @TargetClass(value = "android.view.View", scope = ALL) -// @TargetMethod(methodName = "post") -// @ReplaceInvoke -// fun postOfViewProxy(view: View, action: Runnable): Boolean { -// return if (Looper.myLooper() != Looper.getMainLooper()) { -// UiThreadHandler.post(action) -// } else { -// view.post(action) -// } -// } -// -// @JvmStatic -// @TargetClass(value = "android.view.View", scope = ALL) -// @TargetMethod(methodName = "postDelayed") -// @ReplaceInvoke -// fun postDelayedOfViewProxy(view: View, action: Runnable, delayMillis: Long): Boolean { -// return if (Looper.myLooper() != Looper.getMainLooper()) { -// UiThreadHandler.postDelayed(action, delayMillis) -// } else { -// view.postDelayed(action, delayMillis) -// } -// } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/mogo/launcher/lancet/AsyncHandlerReflectLancet.java b/app/src/main/java/com/mogo/launcher/lancet/jank/AsyncHandlerReflectLancet.java similarity index 90% rename from app/src/main/java/com/mogo/launcher/lancet/AsyncHandlerReflectLancet.java rename to app/src/main/java/com/mogo/launcher/lancet/jank/AsyncHandlerReflectLancet.java index a651fba406..c8d9a89439 100644 --- a/app/src/main/java/com/mogo/launcher/lancet/AsyncHandlerReflectLancet.java +++ b/app/src/main/java/com/mogo/launcher/lancet/jank/AsyncHandlerReflectLancet.java @@ -1,11 +1,10 @@ -package com.mogo.launcher.lancet; +package com.mogo.launcher.lancet.jank; import android.os.Build; import android.os.Handler; import android.os.Looper; import androidx.annotation.Keep; -import androidx.annotation.NonNull; import com.knightboost.lancet.api.Scope; import com.knightboost.lancet.api.annotations.Group; @@ -19,11 +18,6 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.concurrent.CopyOnWriteArraySet; -import kotlin.coroutines.CoroutineContext; -import kotlinx.coroutines.CoroutineExceptionHandler; -import kotlinx.coroutines.Dispatchers; -import kotlinx.coroutines.MainCoroutineDispatcher; - @Keep @Weaver diff --git a/app/src/main/java/com/mogo/launcher/lancet/MainBlockCheck.kt b/app/src/main/java/com/mogo/launcher/lancet/jank/MainBlockCheck.kt similarity index 78% rename from app/src/main/java/com/mogo/launcher/lancet/MainBlockCheck.kt rename to app/src/main/java/com/mogo/launcher/lancet/jank/MainBlockCheck.kt index 14b4401f1a..5bcf518c22 100644 --- a/app/src/main/java/com/mogo/launcher/lancet/MainBlockCheck.kt +++ b/app/src/main/java/com/mogo/launcher/lancet/jank/MainBlockCheck.kt @@ -1,4 +1,4 @@ -package com.mogo.launcher.lancet +package com.mogo.launcher.lancet.jank import android.app.* import android.content.* @@ -515,7 +515,9 @@ class MainBlockCheck { return handler.removeCallbacks(action, token) } val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action) - getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what, if (token != null) { synchronized(tokens) { tokens.remove(token.hashCode())?.get() } } else null) + getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what, if (token != null) { synchronized( + tokens + ) { tokens.remove(token.hashCode())?.get() } } else null) remove(what) } @@ -550,7 +552,9 @@ class MainBlockCheck { if (Looper.getMainLooper() != handler.looper) { return handler.removeMessages(what, token) } - getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what, if (token != null) synchronized(tokens) { tokens.remove(token.hashCode())?.get() } else null) + getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what, if (token != null) synchronized( + tokens + ) { tokens.remove(token.hashCode())?.get() } else null) remove(what) } @@ -559,30 +563,30 @@ class MainBlockCheck { } fun insert(what: Int, holder: Holder) { - val action = getAction() - action.type = 0 - action.what = what - action.holder = holder - pool.execute(action) +// val action = getAction() +// action.type = 0 +// action.what = what +// action.holder = holder +// pool.execute(action) } private fun remove(what: Int) { - val action = getAction() - action.type = 1 - action.what = what - pool.execute(action) +// val action = getAction() +// action.type = 1 +// action.what = what +// pool.execute(action) } - fun recycle(holder: Holder, elapsedTime: Long, duration: Long) { - val action = getAction() - action.type = 2 - action.holder = holder - action.elapsedTime = elapsedTime - action.duration = duration - pool.execute(action) + private fun recycle(holder: Holder, elapsedTime: Long, duration: Long) { +// val action = getAction() +// action.type = 2 +// action.holder = holder +// action.elapsedTime = elapsedTime +// action.duration = duration +// pool.execute(action) } - fun getHandler(isAsync: Boolean): Handler { + private fun getHandler(isAsync: Boolean): Handler { return if (isAsync) { ASYNC_HANDLER } else { @@ -591,114 +595,26 @@ class MainBlockCheck { } } - - - @TargetClass(value = "android.view.View", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onMeasure") - fun proxyViewOnMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - val holder = Holder.acquire(handler = null, obj = "View[${This.get().javaClass.name}]:onMeasure") - pool.execute { - getRecorder()?.insert(holder) - } - val now = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t - } finally { - val spend = now() - now - pool.execute { - getRecorder()?.recycle(holder.id, 0, spend) - } - } - } - - @TargetClass(value = "android.view.View", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onLayout") - fun proxyViewOnLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { - val holder = Holder.acquire(handler = null, obj = "View[${This.get().javaClass.name}]:onLayout") - insert(-1, holder) - val now = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t - } finally { - val spend = now() - now - recycle(holder, 0, spend) - } - } - - - @TargetClass(value = "android.view.View", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onDraw") - fun proxyViewOnDraw(canvas: Canvas) { - val holder = Holder.acquire(handler = null, obj = "View[${This.get().javaClass.name}]:onDraw") - insert(-1, holder) - val now = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t - } finally { - val spend = now() - now - recycle(holder, 0, spend) - } - } - @TargetClass(value = "android.app.Activity", scope = LEAF) @Insert(mayCreateSuper = true) @TargetMethod(methodName = "onCreate") fun proxyActivityOnCreate(savedInstanceState: Bundle?) { - val holder = Holder.acquire(handler = null, obj = "Activity[${This.get().javaClass.name}]:onCreate") - insert(-1, holder) - val now = now() try { Origin.callVoid() - } catch (t: Throwable) { - throw t } finally { - val spend = now() - now CallerDevaToolsManager.block()?.monitor((This.get() as Activity).window) - recycle(holder, 0, spend) } } - @TargetClass(value = "android.app.Activity", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onStart") - fun proxyActivityOnStart() { - val holder = Holder.acquire(handler = null, obj = "Activity[${This.get().javaClass.name}]:onStart") - insert(-1, holder) - val now = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t - } finally { - val spend = now() - now - recycle(holder, 0, spend) - } - } @TargetClass(value = "android.app.Activity", scope = LEAF) @Insert(mayCreateSuper = true) @TargetMethod(methodName = "onResume") fun proxyActivityOnResume() { - val holder = Holder.acquire(handler = null, obj = "Activity[${This.get().javaClass.name}]:onResume") - insert(-1, holder) - val now = now() - CallerDevaToolsManager.block()?.resume((This.get() as Activity).window) try { Origin.callVoid() - } catch (t: Throwable) { - throw t } finally { - val spend = now() - now - recycle(holder, 0, spend) + CallerDevaToolsManager.block()?.resume((This.get() as Activity).window) } } @@ -706,17 +622,10 @@ class MainBlockCheck { @Insert(mayCreateSuper = true) @TargetMethod(methodName = "onPause") fun proxyActivityOnPause() { - val holder = Holder.acquire(handler = null, obj = "Activity[${This.get().javaClass.name}]:onPause") - insert(-1, holder) - CallerDevaToolsManager.block()?.pause((This.get() as Activity).window) - val now = now() try { Origin.callVoid() - } catch (t: Throwable) { - throw t } finally { - val spend = now() - now - recycle(holder, 0, spend) + CallerDevaToolsManager.block()?.pause((This.get() as Activity).window) } } @@ -724,79 +633,10 @@ class MainBlockCheck { @Insert(mayCreateSuper = true) @TargetMethod(methodName = "onDestroy") fun proxyActivityOnDestroy() { - CallerDevaToolsManager.block()?.pop((This.get() as Activity).window) try { Origin.callVoid() - } catch (t: Throwable) { - throw t - } - } - - @TargetClass(value = "androidx.fragment.app.Fragment", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onCreateView") - fun proxyFragmentOnCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?) { - val holder = Holder.acquire(handler = null, obj = "Fragment[${This.get().javaClass.name}]:onCreateView") - insert(-1, holder) - val startTime = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t } finally { - val spend = now() - startTime - recycle(holder, 0, spend) - } - } - - @TargetClass(value = "androidx.fragment.app.Fragment", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onCreate") - fun proxyFragmentOnCreate(savedInstanceState: Bundle?) { - val holder = Holder.acquire(handler = null, obj = "Fragment[${This.get().javaClass.name}]:onCreate") - insert(-1, holder) - val startTime = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t - } finally { - val spend = now() - startTime - recycle(holder, 0, spend) - } - } - - @TargetClass(value = "androidx.fragment.app.Fragment", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onViewCreated") - fun proxyFragmentOnViewCreated(view: View, savedInstanceState: Bundle?) { - val holder = Holder.acquire(handler = null, obj = "Fragment[${This.get().javaClass.name}]:onViewCreated") - insert(-1, holder) - val startTime = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t - } finally { - val spend = now() - startTime - recycle(holder, 0, spend) - } - } - - @TargetClass(value = "android.content.BroadcastReceiver", scope = LEAF) - @Insert(mayCreateSuper = true) - @TargetMethod(methodName = "onReceive") - fun proxyBroadcastReceiver(ctx: Context?, intent: Intent?) { - val holder = Holder.acquire(handler = null, obj = "Receiver[${This.get().javaClass.name}]:onReceive") - insert(-1, holder) - val startTime = now() - try { - Origin.callVoid() - } catch (t: Throwable) { - throw t - } finally { - val spend = now() - startTime - recycle(holder, 0, spend) + CallerDevaToolsManager.block()?.pop((This.get() as Activity).window) } } } \ No newline at end of file diff --git a/app/src/main/java/com/mogo/launcher/lancet/jank/compiler/JankPointAutoGenerator.java b/app/src/main/java/com/mogo/launcher/lancet/jank/compiler/JankPointAutoGenerator.java new file mode 100644 index 0000000000..f85b7e007b --- /dev/null +++ b/app/src/main/java/com/mogo/launcher/lancet/jank/compiler/JankPointAutoGenerator.java @@ -0,0 +1,183 @@ +package com.mogo.launcher.lancet.jank.compiler; + + +import android.app.Activity; +import android.app.ActivityManager; +import android.app.Fragment; +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.ContentProvider; +import android.content.pm.PackageManager; +import android.os.SystemClock; +import android.view.View; + +import com.knightboost.lancet.api.synchronized_lock.ISynchronizedLockHooker; +import com.mogo.core.lancetx.compiler.lib.annotations.LancetXGenerator; +import com.mogo.core.lancetx.compiler.lib.generator.HookType; +import com.mogo.core.lancetx.compiler.lib.generator.Scope; +import com.mogo.core.lancetx.compiler.lib.generator.Type; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.LockSupport; + +class JankPointAutoGenerator { + + @LancetXGenerator( + group = "main_block_check", + type = Type.IPC, + hookAllPublicMethods = true, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private ActivityManager am; + + @LancetXGenerator( + group = "main_block_check", + type = Type.IPC, + hookAllPublicMethods = true, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private PackageManager pm; + + @LancetXGenerator( + group = "main_block_check", + type = Type.ACTIVITY, + mayCreateSuper = true, + hookAllPublicMethods = true, + scope = Scope.LEAF, + hookType = HookType.AROUND, + excludeHookMethodNames = { "runOnUiThread", "toString", "hashCode" }, + excludeHookMethodDescs = { "(Ljava/lang/Runnable;)V", "()Ljava/lang/String;", "()I" } + ) + private Activity activity; + + @LancetXGenerator( + group = "main_block_check", + type = Type.BROADCAST_RECEIVER, + mayCreateSuper = true, + hookType = HookType.AROUND, + hookAllPublicMethods = true, + scope = Scope.LEAF, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private BroadcastReceiver receiver; + + @LancetXGenerator( + group = "main_block_check", + type = Type.CONTENT_PROVIDER, + mayCreateSuper = true, + hookType = HookType.AROUND, + hookAllPublicMethods = true, + scope = Scope.LEAF, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private ContentProvider provider; + + @LancetXGenerator( + group = "main_block_check", + type = Type.SERVICE, + hookAllPublicMethods = true, + mayCreateSuper = true, + hookType = HookType.AROUND, + scope = Scope.LEAF, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private Service service; + + @LancetXGenerator( + group = "main_block_check", + type = Type.AQS_LOCK, + hookAllPublicMethods = true, + scope = Scope.ALL, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private Lock lock; + + @LancetXGenerator( + group = "main_block_check", + type = Type.SLEEP, + scope = Scope.ALL, + onlyHookMethodNames = { "sleep", "sleep"}, + onlyHookMethodDescs = { "(J)V", "(JI)V"}, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private Thread thread; + + + @LancetXGenerator( + group = "main_block_check", + type = Type.SYNCHRONIZED_LOCK, + hookType = HookType.AROUND, + scope = Scope.LEAF, + mayCreateSuper = true, + hookAllPublicMethods = true, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private ISynchronizedLockHooker synchronizedLock; + + + @LancetXGenerator( + group = "main_block_check", + type = Type.PARK, + scope = Scope.ALL, + hookAllPublicMethods = true, + excludeHookMethodNames = { "unpark", "getBlocker", "toString", "hashCode" }, + excludeHookMethodDescs = { "(Ljava/lang/Thread;)V", "(Ljava/lang/Thread;)Ljava/lang/Object;", "()Ljava/lang/String;", "()I"} + ) + private LockSupport park; + + + @LancetXGenerator( + group = "main_block_check", + type = Type.SLEEP, + scope = Scope.ALL, + onlyHookMethodNames = { "sleep" }, + onlyHookMethodDescs = { "(J)V" } + ) + private SystemClock systemClockSleep; + + + @LancetXGenerator( + group = "main_block_check", + type = Type.VIEW, + scope = Scope.LEAF, + hookType = HookType.AROUND, + mayCreateSuper = true, + onlyHookMethodNames = { "onMeasure", "onLayout", "onDraw", "draw" }, + onlyHookMethodDescs = { "(II)V", "(ZIIII)V", "(Landroid/graphics/Canvas;)V", "(Landroid/graphics/Canvas;)V" } + ) + private View view; + + + @LancetXGenerator( + group = "main_block_check", + type = Type.FRAGMENT, + scope = Scope.LEAF, + hookType = HookType.AROUND, + mayCreateSuper = true, + hookAllPublicMethods = true, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + + ) + private Fragment systemFragment; + + @LancetXGenerator( + group = "main_block_check", + type = Type.FRAGMENT, + scope = Scope.LEAF, + hookType = HookType.AROUND, + mayCreateSuper = true, + hookAllPublicMethods = true, + excludeHookMethodNames = { "toString", "hashCode" }, + excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" } + ) + private androidx.fragment.app.Fragment androidxFragment; +} diff --git a/app/src/main/java/com/mogo/launcher/lancet/jank/spi/HookHandler.java b/app/src/main/java/com/mogo/launcher/lancet/jank/spi/HookHandler.java new file mode 100644 index 0000000000..0e27554c5a --- /dev/null +++ b/app/src/main/java/com/mogo/launcher/lancet/jank/spi/HookHandler.java @@ -0,0 +1,90 @@ +package com.mogo.launcher.lancet.jank.spi; +import android.os.Looper; +import android.os.SystemClock; +import android.util.Log; +import androidx.annotation.NonNull; +import com.google.auto.service.AutoService; +import com.mogo.core.lancetx.compiler.lib.generator.Type; +import com.mogo.core.lancetx.compiler.lib.hook.IHookInvoker; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + + +@AutoService(IHookInvoker.class) +public class HookHandler implements IHookInvoker { + + private final Looper mainLooper = Looper.getMainLooper(); + + + private final AtomicLong startTime = new AtomicLong(0L); + + private final ThreadLocal message = new ThreadLocal<>(); + + @Override + public void i(@NonNull Type type, Object caller, @NonNull String methodName, @NonNull Object... objects) { + if (Looper.myLooper() == mainLooper) { + startTime.set(SystemClock.elapsedRealtime()); + } + } + + @Override + public void o(@NonNull Type type, Object caller, @NonNull String methodName, @NonNull Object... objects) { + if (Looper.myLooper() == mainLooper) { + long startTime = this.startTime.get(); + if (startTime > 0) { + long delta = SystemClock.elapsedRealtime() - startTime; + if (delta >= 10) { + StringBuilder builder = message.get(); + if (builder == null) { + builder = new StringBuilder(); + message.set(builder); + } + if (builder.length() > 0) { + builder.setLength(0); + } + builder + .append(type) + .append("#") + .append(caller == null ? "caller is null" : caller.getClass().getSimpleName()) + .append("#") + .append(methodName); + if (objects.length > 0) { + builder.append("#("); + } + for (Object o : objects) { + if (o == null) { + continue; + } + builder.append(o.getClass().getSimpleName()) + .append(","); + } + + if (objects.length > 0) { + builder.setLength(builder.length() - 1); + builder.append(")"); + } + if (type == Type.SYNCHRONIZED_LOCK || type == Type.AQS_LOCK) { + builder.append("\n"); + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + for (StackTraceElement trace: stackTrace) { + if ("dalvik.system.VMStack".equals(trace.getClassName()) && "getThreadStackTrace".equals(trace.getMethodName())) { + continue; + } + if ("java.lang.Thread".equals(trace.getClassName()) && "getStackTrace".equals(trace.getMethodName())) { + continue; + } + builder.append(trace.getClassName()).append("#").append(trace.getMethodName()).append("#").append(trace.getLineNumber()).append("\n"); + } + builder.setLength(builder.length() - 1); + } + Log.w("HookHandler", "jank detected:" + builder); + } + } + } + } + + +} diff --git a/build.gradle b/build.gradle index 214e6b777c..477a0c2815 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ buildscript { classpath "com.mogo.cloud:systrace:${plugin_version}" classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.18' classpath "com.mogo.sticky:service:${plugin_version}" - classpath "io.github.knight-zxw:lancet-plugin:${lancetx_plugin_version}" + classpath "io.github.knight-zxw:lancet-plugin:10.1.0" classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.15.0" classpath 'com.mogo.cloud:matrix:1.0.0' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513' diff --git a/config.gradle b/config.gradle index 449a94ec7c..9d43dfccef 100644 --- a/config.gradle +++ b/config.gradle @@ -208,7 +208,11 @@ ext { //========================= LancetX =================== - lancetx_runtime : "io.github.knight-zxw:lancet-runtime:0.0.4_mogo", + lancetx_runtime : "io.github.knight-zxw:lancet-runtime:10.2.0", + + lancetx_compiler : "com.mogo.eagle.core.lancetx:compiler:1.0.0", + + lancetx_compiler_lib : "com.mogo.eagle.core.lancetx:runtime:1.0.0", //========================= autosize ====================== androidautoSize : 'com.github.JessYanCoding:AndroidAutoSize:v1.2.1', @@ -225,7 +229,10 @@ ext { passport_secret : "com.zhidaoauto:sdk-java:1.0.5-SNAPSHOT", // 主线程卡顿监测 - block_detector : "com.mogo.eagle.core.block:runtime:10.0.21" + block_detector : "com.mogo.eagle.core.block:runtime:10.0.21", + + //======================== google auto-service =============== + google_auto_service : "com.google.auto.service:auto-service:1.0-rc7" ] android = [ fLauncherApplicationId : "com.mogo.launcher.f", diff --git a/gradle/bytex/bytex_lancetx.gradle b/gradle/bytex/bytex_lancetx.gradle index ca8aa1f7a4..85da651fd0 100644 --- a/gradle/bytex/bytex_lancetx.gradle +++ b/gradle/bytex/bytex_lancetx.gradle @@ -2,10 +2,11 @@ apply plugin: 'LancetX' LancetX { enable true enableInDebug true + synchronizedLock { + enabled true + } weaveGroup { - anr_fix { - enable true - } + crash_fix { enable true } @@ -19,7 +20,7 @@ LancetX { enable true } main_block_check { - enable false + enable true } } }