[6.2.0][技术优化] release版本卡顿检测关掉

This commit is contained in:
renwj
2023-11-24 19:39:49 +08:00
parent 516c97a83b
commit 75953d3387
7 changed files with 26 additions and 13 deletions

View File

@@ -1,409 +0,0 @@
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.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.os.SystemClock;
import android.view.View;
import android.view.ViewManager;
import android.widget.Toast;
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.io.File;
import java.io.InputStream;
import java.nio.channels.FileChannel;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
class JankPointAutoGenerator {
@LancetXGenerator(
group = "main_block_check",
type = Type.IPC,
hookAllPublicMethods = true
)
private ActivityManager am;
@LancetXGenerator(
group = "main_block_check",
type = Type.IPC,
hookAllPublicMethods = true
)
private PackageManager pm;
@LancetXGenerator(
group = "main_block_check",
type = Type.ACTIVITY,
mayCreateSuper = true,
hookAllPublicMethods = true,
scope = Scope.LEAF,
hookType = HookType.AROUND,
onlyHookMethodNames = {
"onCreate",
"onStart",
"onResume",
"onPause",
"onStop",
"onDestroy",
"onWindowFocusChanged",
"dispatchKeyEvent",
"dispatchTouchEvent"
},
onlyHookMethodDescs = {
"(Landroid/os/Bundle;)V",
"()V",
"()V",
"()V",
"()V",
"()V",
"(Z)V",
"(Landroid/view/KeyEvent;)Z",
"(Landroid/view/MotionEvent;)Z"
}
)
private Activity activity;
@LancetXGenerator(
group = "main_block_check",
type = Type.BROADCAST_RECEIVER,
mayCreateSuper = true,
hookType = HookType.AROUND,
hookAllPublicMethods = true,
scope = Scope.LEAF,
onlyHookMethodNames = {
"onReceive"
},
onlyHookMethodDescs = {
"(Landroid/content/Context;Landroid/content/Intent;)V"
}
)
private BroadcastReceiver receiver;
@LancetXGenerator(
group = "main_block_check",
type = Type.CONTENT_PROVIDER,
mayCreateSuper = true,
hookType = HookType.AROUND,
hookAllPublicMethods = true,
scope = Scope.LEAF,
onlyHookMethodNames = {
"attachInfo",
"onCreate",
"query",
"getType",
"insert",
"update",
"delete",
"openFile"
},
onlyHookMethodDescs = {
"(Landroid/content/Context;Landroid/content/pm/ProviderInfo;)V",
"()Z",
"(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;",
"(Landroid/net/Uri;)Ljava/lang/String;",
"(Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;",
"(Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I",
"(Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I",
"(Landroid/net/Uri;Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;"
}
)
private ContentProvider provider;
@LancetXGenerator(
group = "main_block_check",
type = Type.SERVICE,
hookAllPublicMethods = true,
mayCreateSuper = true,
hookType = HookType.AROUND,
scope = Scope.LEAF,
onlyHookMethodNames = {
"onCreate",
"onStart",
"onStartCommand",
"onDestroy",
"onConfigurationChanged",
"onLowMemory",
"onTrimMemory",
"onBind",
"onUnbind",
"onRebind",
"onTaskRemoved"
},
onlyHookMethodDescs = {
"()V",
"(Landroid/content/Intent;I)V",
"(Landroid/content/Intent;II)I",
"()V",
"(Landroid/content/res/Configuration;)V",
"()V",
"(I)V",
"(Landroid/content/Intent;)Landroid/os/IBinder;",
"(Landroid/content/Intent;)Z",
"(Landroid/content/Intent;)V",
"(Landroid/content/Intent;)V",
}
)
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",
"join",
"join",
"join",
"getStackTrace",
"getAllStackTraces"
},
onlyHookMethodDescs = {
"(J)V",
"(JI)V",
"(J)V",
"(JI)V",
"()V",
"()[Ljava/lang/StackTraceElement;",
"()Ljava/util/Map;"
}
)
private Thread thread;
@LancetXGenerator(
group = "main_block_check",
type = Type.SYNCHRONIZED_LOCK,
hookType = HookType.AROUND,
scope = Scope.LEAF,
mayCreateSuper = true,
hookAllPublicMethods = true
)
private ISynchronizedLockHooker synchronizedLock;
@LancetXGenerator(
group = "main_block_check",
type = Type.PARK,
scope = Scope.ALL,
hookAllPublicMethods = true
)
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,
onlyHookMethodNames = {
"onAttach",
"onCreate",
"onCreateView",
"onViewCreated",
"onActivityCreated",
"onViewStateRestored",
"onStart",
"onResume",
"onSaveInstanceState",
"onConfigurationChanged",
"onPause",
"onStop",
"onLowMemory",
"onTrimMemory",
"onDestroyView",
"onDestroy",
"onDetach",
},
onlyHookMethodDescs = {
"(Landroid/content/Context;)V",
"(Landroid/os/Bundle;)",
"(Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Landroid/os/Bundle;)Landroid/view/View;",
"(Landroid/view/View;Landroid/os/Bundle;)V",
"(Landroid/os/Bundle;)V",
"(Landroid/os/Bundle;)V",
"()V",
"()V",
"(Landroid/os/Bundle;)V",
"(Landroid/content/res/Configuration;)V",
"()V",
"()V",
"()V",
"(I)V",
"()V",
"()V",
"()V",
}
)
private Fragment systemFragment;
@LancetXGenerator(
group = "main_block_check",
type = Type.FRAGMENT,
scope = Scope.LEAF,
hookType = HookType.AROUND,
mayCreateSuper = true,
hookAllPublicMethods = true,
onlyHookMethodNames = {
"onAttach",
"onCreate",
"onCreateView",
"onViewCreated",
"onActivityCreated",
"onViewStateRestored",
"onStart",
"onResume",
"onSaveInstanceState",
"onConfigurationChanged",
"onPause",
"onStop",
"onLowMemory",
"onDestroyView",
"onDestroy",
"onDetach",
},
onlyHookMethodDescs = {
"(Landroid/content/Context;)V",
"(Landroid/os/Bundle;)",
"(Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Landroid/os/Bundle;)Landroid/view/View;",
"(Landroid/view/View;Landroid/os/Bundle;)V",
"(Landroid/os/Bundle;)V",
"(Landroid/os/Bundle;)V",
"()V",
"()V",
"(Landroid/os/Bundle;)V",
"(Landroid/content/res/Configuration;)V",
"()V",
"()V",
"()V",
"()V",
"()V",
"()V",
}
)
private androidx.fragment.app.Fragment androidxFragment;
@LancetXGenerator(
group = "main_block_check",
type = Type.IO,
scope = Scope.ALL,
hookType = HookType.REPLACE_INVOKE,
hookAllPublicMethods = true,
excludeHookMethodNames = { "toString", "hashCode", "compareTo", "compareTo" },
excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" , "(Ljava/io/File;)I", "(Ljava/lang/Object;)I" }
)
private File file;
@LancetXGenerator(
group = "main_block_check",
type = Type.IO,
scope = Scope.ALL,
hookType = HookType.REPLACE_INVOKE,
hookAllPublicMethods = true,
excludeHookMethodNames = { "toString", "hashCode" },
excludeHookMethodDescs = { "()Ljava/lang/String;", "()I" }
)
private InputStream is;
@LancetXGenerator(
group = "main_block_check",
type = Type.IPC,
scope = Scope.ALL,
hookType = HookType.REPLACE_INVOKE,
hookAllPublicMethods = true,
onlyHookMethodNames = { "show" },
onlyHookMethodDescs = { "()V" }
)
private Toast toast;
@LancetXGenerator(
group = "main_block_check",
type = Type.IPC,
scope = Scope.ALL,
hookType = HookType.REPLACE_INVOKE,
hookAllPublicMethods = true,
onlyHookMethodNames = { "addView", "updateViewLayout", "removeView" },
onlyHookMethodDescs = {
"(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V",
"(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V",
"(Landroid/view/View;)V"
}
)
private ViewManager manager;
@LancetXGenerator(
group = "main_block_check",
type = Type.OTHER,
scope = Scope.LEAF,
mayCreateSuper = true,
hookType = HookType.AROUND,
onlyHookMethodNames = {
"onDrawFrame"
},
onlyHookMethodDescs = {
"(Ljavax/microedition/khronos/opengles/GL10;)V"
}
)
private GLSurfaceView.Renderer renderer;
@LancetXGenerator(
group = "main_block_check",
type = Type.IO,
scope = Scope.SELF,
hookType = HookType.REPLACE_INVOKE,
hookAllPublicMethods = true
)
private BitmapFactory factory;
}

View File

@@ -1,146 +0,0 @@
package com.mogo.launcher.lancet.jank.spi
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.os.SystemClock
import com.google.auto.service.AutoService
import com.mogo.eagle.core.block.runtime.config.recorder.IMessageRecorder
import com.mogo.eagle.core.block.runtime.utils.TimeUtils.Companion.now
import com.mogo.eagle.core.function.api.devatools.perf.IMoGoCpuUsageProvider
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager.block
import com.mogo.eagle.core.function.main.ARouterUtils
import com.mogo.eagle.core.handler.loader.IHandlerHooker
import com.mogo.eagle.core.block.runtime.message.Message as Msg
@AutoService(IHandlerHooker::class)
class HandlerHookerImpl : IHandlerHooker {
private val mainLooper = Looper.getMainLooper()
private var recorder: IMessageRecorder? = null
private var usage: IMoGoCpuUsageProvider? = null
private var dispatchTime = 0L
override fun onMessageDispatchAfter(msg: Message) {
if (msg.target.looper != mainLooper) {
return
}
if (dispatchTime <= 0) {
return
}
val duration = now() - dispatchTime
checkIfNeed(msg.target)?.recycle(Msg.acquire(msg.target, msg = msg, duration = duration, elapsed = SystemClock.uptimeMillis() - msg.`when`, enqueue = msg.`when`))
}
override fun onMessageDispatchBefore(msg: Message) {
if (msg.target.looper != mainLooper) {
return
}
dispatchTime = now()
}
override fun onRemoveCallbacks(handler: Handler, action: Runnable) {
checkIfNeed(handler)?.remove(Msg.acquire(handler, action = action))
}
override fun onRemoveCallbacksAndMessages(handler: Handler, token: Any?) {
checkIfNeed(handler)?.remove(Msg.acquire(handler, obj = token))
}
override fun onRemoveCallbacksWithToken(handler: Handler, action: Runnable, token: Any?) {
checkIfNeed(handler)?.remove(Msg.acquire(handler, action = action, obj = token))
}
override fun onRemoveMessages(handler: Handler, what: Int) {
checkIfNeed(handler)?.remove(Msg.acquire(handler, what = what))
}
override fun onRemoveMessages(handler: Handler, what: Int, obj: Any?) {
checkIfNeed(handler)?.remove(Msg.acquire(handler, what = what, obj = obj))
}
override fun onPost(handler: Handler, action: Runnable) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, action = action))
}
override fun onPostAtFrontQueue(handler: Handler, action: Runnable) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, action = action))
}
override fun onPostAtTime(handler: Handler, action: Runnable, token: Any?, uptimeMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, action = action, obj = token, enqueue = uptimeMillis))
}
override fun onPostAtTime(handler: Handler, action: Runnable, uptimeMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, action = action, enqueue = uptimeMillis))
}
override fun onPostDelayed(handler: Handler, action: Runnable, token: Any?, delayMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, action = action, obj = token, delay = delayMillis))
}
override fun onPostDelayed(handler: Handler, action: Runnable, delayMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, action = action, delay = delayMillis))
}
override fun onSendEmptyMessage(handler: Handler, what: Int) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, what = what))
}
override fun onSendEmptyMessageAtTime(handler: Handler, what: Int, uptimeMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, what = what, enqueue = uptimeMillis))
}
override fun onSendEmptyMessageDelayed(handler: Handler, what: Int, delayMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, what = what, delay = delayMillis))
}
override fun onSendMessage(handler: Handler, msg: Message) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, msg, what = msg.what))
}
override fun onSendMessageAtFrontOfQueue(handler: Handler, msg: Message) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, msg, what = msg.what))
}
override fun onSendMessageAtTime(handler: Handler, msg: Message, uptimeMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, msg = msg, enqueue = uptimeMillis))
}
override fun onSendMessageDelayed(handler: Handler, msg: Message, delayMillis: Long) {
checkIfNeed(handler)?.insert(Msg.acquire(handler, msg = msg, delay = delayMillis))
}
private fun checkIfNeed(handler: Handler?): IMessageRecorder? {
var usage = this.usage
if (usage == null && ARouterUtils.isInit.get()) {
usage = CallerDevaToolsManager.usage()
this.usage = usage
}
if (handler != null) {
if (handler.looper != mainLooper) {
usage?.updateOtherThreadTime()
} else {
usage?.updateMainThreadTime()
}
}
if (handler != null && handler.looper != mainLooper) {
return null
}
if (recorder == null) {
val hasInit = ARouterUtils.isInit.get()
if (hasInit && recorder == null) {
val block = block()
if (block != null && block.hasInit()) {
recorder = block.recorder()
}
}
}
return recorder
}
}

View File

@@ -1,302 +0,0 @@
package com.mogo.launcher.lancet.jank.spi;
import android.app.Activity;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
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 com.mogo.eagle.core.data.deva.chain.ChainConstant;
import com.mogo.eagle.core.function.api.devatools.block.IMoGoBlockProvider;
import com.mogo.eagle.core.function.api.devatools.perf.IMoGoCpuUsageProvider;
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager;
import com.mogo.eagle.core.function.main.ARouterUtils;
import com.zhjt.service.chain.ChainLog;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
@AutoService(IHookInvoker.class)
public class HookInvokerImpl implements IHookInvoker {
private final Looper mainLooper = Looper.getMainLooper();
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
private final ThreadLocal<StringBuilder> message = new ThreadLocal<>();
private final ThreadLocal<Object> monitor = new ThreadLocal<>();
private final AtomicReference<Thread> holder = new AtomicReference<>();
private final StringBuilder extra = new StringBuilder();
private volatile IMoGoCpuUsageProvider provider;
private volatile boolean getProviderRequested = false;
private volatile boolean isCanDump = false; // 是否可以Dump堆栈加此标记位是防止应用启动过程中由于dump主线程堆栈导致启动耗时
// 切记: 请勿在此方法中调用其它模块类中的api,可能会出现StackOverFlowException
@Override
public void i(Type type, Object caller,String methodName, Object... objects) {
startTime.set(SystemClock.elapsedRealtime());
boolean isMainThread = mainLooper == Looper.myLooper();
if (type == Type.SYNCHRONIZED_LOCK) {
handleSynchronizedLock(isMainThread, caller, methodName, objects);
}
if (type == Type.AQS_LOCK) {
handleAqsLockEnterBefore(isMainThread, caller, methodName, objects);
}
if (!getProviderRequested && provider == null && mainLooper != Looper.myLooper() && ARouterUtils.isInit.get()) {
getProviderRequested = true;
new Thread(() -> {
try {
provider = CallerDevaToolsManager.INSTANCE.usage();
} finally {
getProviderRequested = false;
}
}, "getProvider").start();
}
if (provider != null) {
if (isMainThread) {
provider.updateMainThreadTime();
} else {
provider.updateOtherThreadTime();
}
}
}
// 切记: 请勿在此方法中调用其它模块类中的api,可能会出现StackOverFlowException
@Override
public void o(Type type, Object caller,String methodName, Object... args) {
long now = SystemClock.elapsedRealtime();
Long old = startTime.get();
long cost = now - (old == null ? now : old);
boolean isMainThread = mainLooper == Looper.myLooper();
if (isMainThread && type != Type.SYNCHRONIZED_LOCK) {
handleCostTimeRecord(type, null, caller, methodName, cost, args);
}
if (isMainThread && type == Type.ACTIVITY) {
handleActivity((Activity) caller, methodName, args);
}
if (type == Type.AQS_LOCK) {
handleAqsLockEnterAfter(isMainThread, caller, methodName, args);
}
if (provider != null) {
if (isMainThread) {
provider.updateMainThreadTime();
} else {
provider.updateOtherThreadTime();
}
}
}
private void handleAqsLockEnterBefore(boolean isMainThread, Object caller, String methodName, Object[] objects) {
if (isMainThread && caller instanceof Lock) {
if ("lock".equals(methodName) || "lockInterruptibly".equals(methodName)) {
if (extra.length() > 0) {
extra.setLength(0);
}
extra.append(caller);
}
}
}
private void handleAqsLockEnterAfter(boolean isMainThread, Object caller, String methodName, Object[] objects) {
if (isMainThread && caller instanceof Lock) {
if ("lock".equals(methodName) || "lockInterruptibly".equals(methodName)) {
Long start = startTime.get();
if (start != null) {
long dur = SystemClock.elapsedRealtime() - start;
handleCostTimeRecord(Type.AQS_LOCK, extra, caller, methodName, dur, objects);
}
}
}
}
private void handleCostTimeRecord(Type type, StringBuilder extra, Object caller, String methodName, long cost, Object... args) {
//日志打印阈值
long logThreshold = 5;
if (cost >= logThreshold) {
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().getName())
.append("#")
.append(methodName);
if (args.length > 0) {
builder.append("#(");
}
for (Object o : args) {
if (o == null) {
continue;
}
builder.append(o.getClass().getName())
.append(",");
}
if (args.length > 0) {
builder.setLength(builder.length() - 1);
builder.append(")");
}
builder.append("#").append(cost);
boolean flag = false;
if (extra != null && extra.length() > 0) {
builder.append("#");
builder.append(extra);
flag = true;
}
// dump堆栈阈值
long dumpStackThreshold = 20;
if (cost >= dumpStackThreshold && isCanDump) {
builder.append("\n");
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (StackTraceElement trace: stackTrace) {
builder.append(trace.getClassName()).append("#").append(trace.getMethodName()).append("#").append(trace.getLineNumber()).append("\n");
}
builder.setLength(builder.length() - 1);
}
Log.w("HookHandler", "Junk Detected:" + builder);
linkedLog(type, builder.toString());
if (flag) {
extra.setLength(0);
}
}
}
private void handleActivity(Activity caller, String methodName, Object... args) {
if ("onCreate".equals(methodName)) {
try {
IMoGoBlockProvider block = CallerDevaToolsManager.INSTANCE.block();
if (block != null && block.hasInit()) {
block.monitor(caller.getWindow());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if ("onResume".equals(methodName)) {
try {
IMoGoBlockProvider block = CallerDevaToolsManager.INSTANCE.block();
if (block != null && block.hasInit()) {
block.resume(caller.getWindow());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if ("onWindowFocusChanged".equals(methodName)) {
if (args.length > 0) {
boolean hasFocus = (boolean)args[0];
if (hasFocus && !isCanDump) {
isCanDump = true;
}
}
}
if ("onPause".equals(methodName)) {
try {
IMoGoBlockProvider block = CallerDevaToolsManager.INSTANCE.block();
if (block != null && block.hasInit()) {
block.pause(caller.getWindow());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if ("onStop".equals(methodName)) {
try {
IMoGoBlockProvider block = CallerDevaToolsManager.INSTANCE.block();
if (block != null && block.hasInit()) {
block.pop(caller.getWindow());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
private void handleSynchronizedLock(boolean isMainThread,Object caller, String methodName, Object [] objects) {
if (isMainThread) {
if ("onMonitorBefore".equals(methodName)) {
Object monitor = null;
if (objects.length > 0) {
this.monitor.set(monitor = objects[0]);
}
Thread holder = this.holder.get();
StringBuilder sb = new StringBuilder();
if (monitor != null) {
sb.append("monitor::").append(monitor.getClass().getName());
}
if (holder != null) {
if (sb.length() > 0) {
sb.append("##holder::").append(holder);
} else {
sb.append("holder::").append(holder);
}
}
if (extra.length() > 0) {
extra.setLength(0);
}
extra.append(sb);
}
if ("onMonitorEnter".equals(methodName)) {
Long startTime = this.startTime.get();
if (startTime == null) {
return;
}
long cost = SystemClock.elapsedRealtime() - startTime;
handleCostTimeRecord(Type.SYNCHRONIZED_LOCK, extra, caller, methodName, cost, objects);
}
if ("onMonitorExit".equals(methodName)) {
this.monitor.remove();
}
} else {
if ("onMonitorBefore".equals(methodName)) {
if (objects.length > 0) {
this.monitor.set(objects[0]);
}
}
if ("onMonitorEnter".equals(methodName)) {
holder.set(Thread.currentThread());
}
if ("onMonitorExit".equals(methodName)) {
this.monitor.remove();
holder.set(null);
}
}
}
private void linkedLog(Type type, String msg) {
try {
linkedLogInternal(type,msg);
} catch (Throwable t) {
t.printStackTrace();
}
}
@ChainLog(
linkChainLog = ChainConstant.CHAIN_TYPE_ANR_LEAK,
linkCode = ChainConstant.CHAIN_SOURCE_HMI,
nodeAliasCode = ChainConstant.CHAIN_CODE_MAIN_BLOCK,
paramIndexes = { 0, 1 }
)
private void linkedLogInternal(Type type, String msg) {}
}

View File

@@ -1,97 +0,0 @@
package com.mogo.launcher.lancet.jank.ui
import android.app.Activity
import android.view.View
import com.knightboost.lancet.api.Scope
import com.knightboost.lancet.api.annotations.Group
import com.knightboost.lancet.api.annotations.ReplaceInvoke
import com.knightboost.lancet.api.annotations.TargetClass
import com.knightboost.lancet.api.annotations.TargetMethod
import com.knightboost.lancet.api.annotations.Weaver
import com.mogo.eagle.core.block.runtime.message.Message
import com.mogo.eagle.core.block.runtime.utils.TimeUtils.Companion.now
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import java.util.concurrent.ConcurrentHashMap
@Weaver
@Group("main_block_check")
class UiPostLancet {
internal data class ActionWrapper(var action: Runnable): Runnable {
override fun run() {
val start = now()
try {
action.run()
} finally {
CallerDevaToolsManager.block()?.takeIf {
it.hasInit()
}?.recorder()?.recycle(Message.acquire(handler = null, action = action, duration = now() - start))
}
}
}
companion object {
private val map by lazy { ConcurrentHashMap<Runnable, ActionWrapper>() }
@JvmStatic
@TargetClass(value = "android.app.Activity", scope = Scope.ALL)
@TargetMethod(methodName = "runOnUiThread")
@ReplaceInvoke
fun runOnUiThreadOfActivity(activity: Activity, action: Runnable) {
try {
activity.runOnUiThread(ActionWrapper(action).also { map[action] = it })
} finally {
CallerDevaToolsManager.block()?.takeIf {
it.hasInit()
}?.recorder()?.insert(Message.acquire(handler = null, action = action, extra = mapOf(activity.javaClass.name to "runOnUiThread")))
}
}
@JvmStatic
@TargetClass(value = "android.view.View", scope = Scope.ALL)
@TargetMethod(methodName = "post")
@ReplaceInvoke
fun post(view: View, action: Runnable): Boolean {
return try {
view.post(ActionWrapper(action).also { map[action] = it })
} finally {
CallerDevaToolsManager.block()?.takeIf {
it.hasInit()
}?.recorder()?.insert(Message.acquire(handler = null, action = action, extra = mapOf(view.javaClass.name to "post")))
}
}
@JvmStatic
@TargetClass(value = "android.view.View", scope = Scope.ALL)
@TargetMethod(methodName = "postDelayed")
@ReplaceInvoke
fun postDelayed(view: View, action: Runnable, delayMillis: Long): Boolean {
return try {
view.postDelayed(action, delayMillis)
} finally {
CallerDevaToolsManager.block()?.takeIf {
it.hasInit()
}?.recorder()?.insert(Message.acquire(handler = null, action = action, extra = mapOf(view.javaClass.name to "post")))
}
}
@JvmStatic
@TargetClass(value = "android.view.View", scope = Scope.ALL)
@TargetMethod(methodName = "removeCallbacks")
@ReplaceInvoke
fun removeCallbacks(view: View, action: Runnable): Boolean {
return try {
view.removeCallbacks(map.remove(action))
} finally {
CallerDevaToolsManager.block()?.takeIf {
it.hasInit()
}?.recorder()?.remove(Message.acquire(handler = null, action = action, extra = mapOf(view.javaClass.name to "removeCallbacks")))
}
}
}
}