[3.4.0][Block] 卡顿检测代码性能优化
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package com.mogo.launcher.lancet;
|
||||
|
||||
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;
|
||||
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 java.lang.ref.WeakReference;
|
||||
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
|
||||
@Group("main_block_check")
|
||||
public class AsyncHandlerReflectLancet {
|
||||
|
||||
|
||||
@TargetClass(value = "java.lang.reflect.Method",scope = Scope.SELF)
|
||||
@TargetMethod(methodName = "invoke")
|
||||
@ReplaceInvoke
|
||||
public static Object hookMethodInvoke(Method method, Object obj, Object... args) throws InvocationTargetException, IllegalAccessException {
|
||||
Object ret = method.invoke(obj, args);
|
||||
if (ret instanceof Handler && "createAsync".equals(method.getName())) {
|
||||
CopyOnWriteArraySet<WeakReference<Handler>> asyncHandlers = MainBlockCheck.Companion.getAsyncHandlers();
|
||||
asyncHandlers.add(new WeakReference<>((Handler) ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@TargetClass(value = "android.os.Handler",scope = Scope.SELF)
|
||||
@TargetMethod(methodName = "createAsync")
|
||||
@ReplaceInvoke(isStatic = true)
|
||||
public static Handler createAsync(Looper looper) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
Handler handler = Handler.createAsync(looper);
|
||||
CopyOnWriteArraySet<WeakReference<Handler>> asyncHandlers = MainBlockCheck.Companion.getAsyncHandlers();
|
||||
asyncHandlers.add(new WeakReference<>(handler));
|
||||
return handler;
|
||||
} else {
|
||||
return new Handler(looper);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetClass(value = "android.os.Handler",scope = Scope.SELF)
|
||||
@TargetMethod(methodName = "createAsync")
|
||||
@ReplaceInvoke(isStatic = true)
|
||||
public static Handler createAsync(Looper looper, Handler.Callback callback) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
Handler handler = Handler.createAsync(looper, callback);
|
||||
CopyOnWriteArraySet<WeakReference<Handler>> asyncHandlers = MainBlockCheck.Companion.getAsyncHandlers();
|
||||
asyncHandlers.add(new WeakReference<>(handler));
|
||||
return handler;
|
||||
} else {
|
||||
return new Handler(looper, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.mogo.launcher.lancet
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Canvas
|
||||
import android.app.*
|
||||
import android.content.*
|
||||
import android.graphics.*
|
||||
import android.os.*
|
||||
import android.os.Handler.Callback
|
||||
import android.util.*
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.*
|
||||
import androidx.annotation.*
|
||||
import androidx.collection.ArrayMap
|
||||
import androidx.core.os.HandlerCompat
|
||||
import com.knightboost.lancet.api.*
|
||||
import com.knightboost.lancet.api.Scope.ALL
|
||||
import com.knightboost.lancet.api.Scope.LEAF
|
||||
@@ -22,8 +21,9 @@ import com.mogo.eagle.core.function.call.devatools.*
|
||||
import com.mogo.eagle.core.utilcode.util.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Runnable
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.LinkedList
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.*
|
||||
import com.mogo.eagle.core.block.runtime.message.Message as Holder
|
||||
|
||||
@Keep
|
||||
@@ -33,11 +33,18 @@ class MainBlockCheck {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
val tokens = ArrayMap<Any, Holder>(128)
|
||||
private const val TAG = "MAIN_BLOCK_CHECK"
|
||||
|
||||
@JvmStatic
|
||||
val whats by lazy { ConcurrentHashMap<Int, LinkedList<Holder>>() }
|
||||
private val tokens = ArrayMap<Any, Holder>(128)
|
||||
|
||||
private val pool by lazy { Executors.newFixedThreadPool(1) }
|
||||
|
||||
val asyncHandlers by lazy { CopyOnWriteArraySet<WeakReference<Handler>>() }
|
||||
|
||||
private val asyncHandlersMap by lazy { ConcurrentHashMap<Int, Boolean>() }
|
||||
|
||||
private val whats by lazy { ConcurrentHashMap<Int, LinkedList<Holder>>() }
|
||||
|
||||
@JvmStatic
|
||||
fun getRecorder(): IMessageRecorder? {
|
||||
@@ -48,20 +55,23 @@ class MainBlockCheck {
|
||||
return block.recorder()
|
||||
}
|
||||
|
||||
@JvmStatic val HANDLER by lazy {
|
||||
Handler(Looper.getMainLooper()) { msg ->
|
||||
val enclose = msg.obj as? Holder ?: throw AssertionError()
|
||||
enclose.what?.also {
|
||||
whats[it]?.remove(enclose)
|
||||
@JvmStatic val callback by lazy {
|
||||
Callback { msg ->
|
||||
val enclose = msg.obj as? Holder
|
||||
if (enclose == null) {
|
||||
Log.w(TAG, "--- handleMessage --- 1 ---")
|
||||
return@Callback true
|
||||
}
|
||||
|
||||
if (!enclose.isValid()) {
|
||||
Log.w(TAG, "--- handleMessage --- 2 ---:$enclose")
|
||||
return@Callback true
|
||||
}
|
||||
val h = enclose.handler
|
||||
val action = enclose.action
|
||||
val oldMsg = enclose.origin
|
||||
val oldObj = enclose.obj
|
||||
val now = now()
|
||||
if (enclose.enqueueTime <= 0) {
|
||||
throw AssertionError("illegal: $enclose")
|
||||
}
|
||||
val elapsedTime = now - enclose.enqueueTime
|
||||
try {
|
||||
if (action != null) {
|
||||
@@ -76,12 +86,22 @@ class MainBlockCheck {
|
||||
}
|
||||
} finally {
|
||||
val duration = now() - now
|
||||
getRecorder()?.recycle(enclose.id, elapsedTime, duration)
|
||||
pool.execute {
|
||||
getRecorder()?.recycle(enclose.id, elapsedTime, duration)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic val ASYNC_HANDLER by lazy {
|
||||
HandlerCompat.createAsync(Looper.getMainLooper(), callback)
|
||||
}
|
||||
|
||||
@JvmStatic val HANDLER by lazy {
|
||||
Handler(Looper.getMainLooper(), callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TargetClass(value = "android.os.Handler", scope = ALL)
|
||||
@TargetMethod(methodName = "post")
|
||||
@@ -90,19 +110,31 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.post(action)
|
||||
}
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(action)
|
||||
val msg = Message.obtain(handler, action)
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
val msg = Message.obtain(newHandler)
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(newHandler, action)
|
||||
msg.what = what
|
||||
val holder = Holder.acquire(handler, action = action, what = what)
|
||||
val holder = Holder.acquire(newHandler, action = action, what = msg.what, isAsync = isAsync)
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessage(msg)
|
||||
val inserted = newHandler.sendMessage(msg)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(what) { LinkedList<Holder>() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
|
||||
private fun getHandler(isAsync: Boolean): Handler {
|
||||
return if (isAsync) {
|
||||
ASYNC_HANDLER
|
||||
} else {
|
||||
HANDLER
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TargetClass(value = "android.os.Handler", scope = ALL)
|
||||
@TargetMethod(methodName = "sendEmptyMessage")
|
||||
@@ -111,13 +143,17 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.sendEmptyMessage(what)
|
||||
}
|
||||
val msg = Message.obtain(handler, what)
|
||||
val holder = Holder.acquire(handler, what = what)
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
val msg = Message.obtain(newHandler, what)
|
||||
val holder = Holder.acquire(handler, what = what, isAsync = isAsync)
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessage(msg)
|
||||
val inserted = newHandler.sendMessage(msg)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(what) { LinkedList<Holder>() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -130,14 +166,20 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.sendEmptyMessageAtTime(what, uptimeMillis)
|
||||
}
|
||||
val msg = Message.obtain(handler, what)
|
||||
val holder = Holder.acquire(handler, what = what, delay = uptimeMillis - SystemClock.uptimeMillis())
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
val msg = Message.obtain(newHandler, what)
|
||||
val delta = uptimeMillis - SystemClock.uptimeMillis()
|
||||
val holder = Holder.acquire(handler, what = what, delay = if (delta > 0) delta else 0, isAsync = isAsync)
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessageAtTime(msg, uptimeMillis)
|
||||
val inserted = newHandler.sendMessageAtTime(msg, uptimeMillis)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(what) { LinkedList<Holder>() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
|
||||
return inserted
|
||||
}
|
||||
|
||||
@@ -149,13 +191,17 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.sendEmptyMessageDelayed(what, delayMillis)
|
||||
}
|
||||
val msg = Message.obtain(handler, what)
|
||||
val holder = Holder.acquire(handler, what = what, delay = delayMillis)
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
val msg = Message.obtain(newHandler, what)
|
||||
val holder = Holder.acquire(handler, what = what, delay = delayMillis, isAsync = isAsync)
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessageDelayed(msg, delayMillis)
|
||||
val inserted = newHandler.sendMessageDelayed(msg, delayMillis)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(what) { LinkedList<Holder>() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -168,18 +214,28 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.sendMessage(msg)
|
||||
}
|
||||
val obj: Holder = Holder.acquire(handler, msg, obj = msg.obj, what = msg.what)
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
var newMsg = msg
|
||||
val action = msg.callback
|
||||
if (action != null) {
|
||||
newMsg = Message.obtain(newHandler)
|
||||
newMsg.what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action)
|
||||
}
|
||||
val obj: Holder = Holder.acquire(handler, originMsg = msg, action = msg.callback, obj = msg.obj, what = msg.what, isAsync = isAsync)
|
||||
val oldObj = msg.obj
|
||||
msg.obj = obj
|
||||
newMsg.obj = obj
|
||||
if (oldObj != null) {
|
||||
synchronized(tokens) {
|
||||
tokens[oldObj] = obj
|
||||
}
|
||||
}
|
||||
val inserted = HANDLER.sendMessage(msg)
|
||||
val inserted = newHandler.sendMessage(newMsg)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(obj)
|
||||
whats.getOrPut(msg.what) { LinkedList() }.add(obj)
|
||||
pool.execute {
|
||||
whats.getOrPut(newMsg.what) { LinkedList<Holder>() }.add(obj)
|
||||
getRecorder()?.insert(obj)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -192,18 +248,29 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.sendMessageAtTime(msg, uptimeMillis)
|
||||
}
|
||||
val obj= Holder.acquire(handler, msg, obj = msg.obj, what = msg.what, delay = uptimeMillis - SystemClock.uptimeMillis())
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
var newMsg = msg
|
||||
val action = msg.callback
|
||||
if (action != null) {
|
||||
newMsg = Message.obtain(newHandler)
|
||||
newMsg.what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action)
|
||||
}
|
||||
val delta = uptimeMillis - SystemClock.uptimeMillis()
|
||||
val obj= Holder.acquire(handler, msg, obj = msg.obj, action = msg.callback, what = msg.what, delay = if (delta > 0) delta else 0, isAsync = isAsync)
|
||||
val oldObj = msg.obj
|
||||
msg.obj = obj
|
||||
newMsg.obj = obj
|
||||
if (oldObj != null) {
|
||||
synchronized(tokens) {
|
||||
tokens[oldObj] = obj
|
||||
}
|
||||
}
|
||||
val inserted = HANDLER.sendMessageAtTime(msg, uptimeMillis)
|
||||
val inserted = newHandler.sendMessageAtTime(newMsg, uptimeMillis)
|
||||
if (inserted) {
|
||||
whats.getOrPut(msg.what) { LinkedList() }.add(obj)
|
||||
getRecorder()?.insert(obj)
|
||||
pool.execute {
|
||||
whats.getOrPut(newMsg.what) { LinkedList<Holder>() }.add(obj)
|
||||
getRecorder()?.insert(obj)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -216,18 +283,28 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.sendMessageAtFrontOfQueue(msg)
|
||||
}
|
||||
val obj = Holder.acquire(handler, msg, obj = msg.obj, what = msg.what)
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
var newMsg = msg
|
||||
val action = msg.callback
|
||||
if (action != null) {
|
||||
newMsg = Message.obtain(newHandler)
|
||||
newMsg.what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action)
|
||||
}
|
||||
val obj = Holder.acquire(handler, msg, obj = msg.obj, action = msg.callback, what = msg.what, isAsync = isAsync)
|
||||
val old = msg.obj
|
||||
msg.obj = obj
|
||||
newMsg.obj = obj
|
||||
if (old != null) {
|
||||
synchronized(tokens) {
|
||||
tokens[old] = obj
|
||||
}
|
||||
}
|
||||
val inserted = HANDLER.sendMessageAtFrontOfQueue(msg)
|
||||
val inserted = newHandler.sendMessageAtFrontOfQueue(newMsg)
|
||||
if (inserted) {
|
||||
whats.getOrPut(msg.what) { LinkedList() }.add(obj)
|
||||
getRecorder()?.insert(obj)
|
||||
pool.execute {
|
||||
whats.getOrPut(newMsg.what) { LinkedList<Holder>() }.add(obj)
|
||||
getRecorder()?.insert(obj)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -240,15 +317,22 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.postDelayed(action, delayMillis)
|
||||
}
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(action)
|
||||
val msg = Message.obtain(handler, action)
|
||||
val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }
|
||||
val newHandler = getHandler(isAsync)
|
||||
val msg = Message.obtain(newHandler)
|
||||
if (isAsync) {
|
||||
msg.isAsynchronous = true
|
||||
}
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action)
|
||||
msg.what = what
|
||||
val holder = Holder.acquire(handler, action = action, what = what, delay = delayMillis)
|
||||
val holder = Holder.acquire(handler, action = action, delay = delayMillis, what = what, isAsync = isAsync)
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessageDelayed(msg, delayMillis)
|
||||
val inserted = newHandler.sendMessageDelayed(msg, delayMillis)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -258,15 +342,17 @@ class MainBlockCheck {
|
||||
@TargetMethod(methodName = "post")
|
||||
@ReplaceInvoke
|
||||
fun runOnUiThreadOfActivityProxy(activity: Activity, action: Runnable) {
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(action)
|
||||
val msg = Message.obtain()
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(activity, action)
|
||||
msg.what = what
|
||||
val holder = Holder.acquire(null, action = action, what = what)
|
||||
val holder = Holder.acquire(null, action = action, what = msg.what, extra = mutableMapOf("runOnUiThread" to "${activity.javaClass.simpleName}#${action.javaClass.name}"))
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessage(msg)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(msg.what) { LinkedList<Holder>() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,15 +361,17 @@ class MainBlockCheck {
|
||||
@TargetMethod(methodName = "post")
|
||||
@ReplaceInvoke
|
||||
fun postOfViewProxy(view: View, action: Runnable): Boolean {
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(action)
|
||||
val msg = Message.obtain()
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(view, action)
|
||||
msg.what = what
|
||||
val holder = Holder.acquire(null, action = action, what = what)
|
||||
val holder = Holder.acquire(null, action = action, what = what, extra = mutableMapOf("post" to "${view.javaClass.simpleName}#${action.javaClass.name}"))
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessage(msg)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(msg.what) { LinkedList<Holder>() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -293,15 +381,17 @@ class MainBlockCheck {
|
||||
@TargetMethod(methodName = "postDelayed")
|
||||
@ReplaceInvoke
|
||||
fun postDelayedOfViewProxy(view: View, action: Runnable, delayMillis: Long): Boolean {
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(action)
|
||||
val msg = Message.obtain()
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(view, action)
|
||||
msg.what = what
|
||||
val holder = Holder.acquire(null, action = action, what = what, delay = delayMillis)
|
||||
val holder = Holder.acquire(null, action = action, delay = delayMillis, what = what, extra = mutableMapOf("post" to "${view.javaClass.simpleName}#${action.javaClass.name}"))
|
||||
msg.obj = holder
|
||||
val inserted = HANDLER.sendMessageDelayed(msg, delayMillis)
|
||||
if (inserted) {
|
||||
getRecorder()?.insert(holder)
|
||||
whats.getOrPut(what) { LinkedList() }.add(holder)
|
||||
pool.execute {
|
||||
whats.getOrPut(msg.what) { LinkedList<Holder>() }.add(holder)
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
}
|
||||
return inserted
|
||||
}
|
||||
@@ -315,11 +405,13 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.removeCallbacks(action)
|
||||
}
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(action)
|
||||
HANDLER.removeMessages(what)
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action)
|
||||
getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what)
|
||||
pool.execute {
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,12 +423,14 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.removeCallbacks(action, token)
|
||||
}
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(action)
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action)
|
||||
getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what, if (token != null) { synchronized(tokens) { tokens.remove(token) } } else null)
|
||||
pool.execute {
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
}
|
||||
}
|
||||
HANDLER.removeMessages(what, if (token != null) { synchronized(tokens) { tokens.remove(token) } } else null)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -347,11 +441,13 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.removeMessages(what)
|
||||
}
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what)
|
||||
pool.execute {
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
}
|
||||
}
|
||||
HANDLER.removeMessages(what)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -362,19 +458,28 @@ class MainBlockCheck {
|
||||
if (Looper.getMainLooper() != handler.looper) {
|
||||
return handler.removeMessages(what, token)
|
||||
}
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what, if (token != null) synchronized(tokens) { tokens.remove(token) } else null)
|
||||
pool.execute {
|
||||
val holders = whats.remove(what)
|
||||
if (!holders.isNullOrEmpty()) {
|
||||
getRecorder()?.remove(holders)
|
||||
}
|
||||
}
|
||||
HANDLER.removeMessages(what, if (token != null) synchronized(tokens) { tokens.remove(token) } else null)
|
||||
}
|
||||
|
||||
private fun computeIsAsyncHandler(handler: Handler): Boolean {
|
||||
return asyncHandlers.find { it.get() === handler } != null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@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()
|
||||
@@ -382,7 +487,9 @@ class MainBlockCheck {
|
||||
throw t
|
||||
} finally {
|
||||
val spend = now() - now
|
||||
getRecorder()?.insert(Holder.acquire(spend, "View[${This.get().javaClass.name}]:onMeasure"))
|
||||
pool.execute {
|
||||
getRecorder()?.recycle(holder.id, 0, spend)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,7 +498,9 @@ class MainBlockCheck {
|
||||
@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")
|
||||
getRecorder()?.insert(holder)
|
||||
pool.execute {
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
val now = now()
|
||||
try {
|
||||
Origin.callVoid()
|
||||
@@ -399,7 +508,9 @@ class MainBlockCheck {
|
||||
throw t
|
||||
} finally {
|
||||
val spend = now() - now
|
||||
getRecorder()?.recycle(holder.id, 0, spend)
|
||||
pool.execute {
|
||||
getRecorder()?.recycle(holder.id, 0, spend)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +520,9 @@ class MainBlockCheck {
|
||||
@TargetMethod(methodName = "onDraw")
|
||||
fun proxyViewOnDraw(canvas: Canvas) {
|
||||
val holder = Holder.acquire(handler = null, obj = "View[${This.get().javaClass.name}]:onDraw")
|
||||
getRecorder()?.insert(holder)
|
||||
pool.execute {
|
||||
getRecorder()?.insert(holder)
|
||||
}
|
||||
val now = now()
|
||||
try {
|
||||
Origin.callVoid()
|
||||
@@ -417,7 +530,9 @@ class MainBlockCheck {
|
||||
throw t
|
||||
} finally {
|
||||
val spend = now() - now
|
||||
getRecorder()?.recycle(holder.id, 0, spend)
|
||||
pool.execute {
|
||||
getRecorder()?.recycle(holder.id, 0, spend)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ ext {
|
||||
passport_secret : "com.zhidaoauto:sdk-java:1.0.5-SNAPSHOT",
|
||||
|
||||
// 主线程卡顿监测
|
||||
block_detector : "com.mogo.eagle.core.block:runtime:10.0.0"
|
||||
block_detector : "com.mogo.eagle.core.block:runtime:10.0.20"
|
||||
]
|
||||
android = [
|
||||
launcherApplicationId : "com.mogo.launcher",
|
||||
|
||||
@@ -11,18 +11,41 @@ public class ObjectHashCodeUtils {
|
||||
|
||||
private static final ConcurrentHashMap<String, Integer> hashCodes = new ConcurrentHashMap<>();
|
||||
|
||||
private static final StringBuilder keyBuilder = new StringBuilder(128);
|
||||
|
||||
public static int getHashCodeIfNeed(Object obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
public static int getHashCodeIfNeed(Object obj1, Object obj2) {
|
||||
if (obj1 == null && obj2 == null) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
String name = obj.getClass().getName();
|
||||
Integer value = hashCodes.get(name);
|
||||
synchronized (keyBuilder) {
|
||||
keyBuilder.setLength(0);
|
||||
boolean flag = false;
|
||||
if (obj1 != null) {
|
||||
flag = true;
|
||||
keyBuilder.append(obj1.hashCode());
|
||||
}
|
||||
if (obj2 != null) {
|
||||
if (flag) {
|
||||
keyBuilder.append("#");
|
||||
}
|
||||
keyBuilder.append(obj2.getClass().getName());
|
||||
}
|
||||
}
|
||||
String key = keyBuilder.toString();
|
||||
Integer value = hashCodes.get(key);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
int hashCode = - System.identityHashCode(obj);
|
||||
hashCodes.put(name, hashCode);
|
||||
Object obj = obj2 == null ? obj1 : obj2;
|
||||
int hashCode = -System.identityHashCode(obj);
|
||||
if (hashCodes.containsValue(hashCode)) {
|
||||
hashCode = -System.identityHashCode(new Object());
|
||||
}
|
||||
hashCodes.put(key, hashCode);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public static int getHashCodeIfNeed(Object obj) {
|
||||
return getHashCodeIfNeed(null, obj);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user