diff --git a/app/src/main/java/com/mogo/launcher/lancet/AsyncHandlerReflectLancet.java b/app/src/main/java/com/mogo/launcher/lancet/AsyncHandlerReflectLancet.java new file mode 100644 index 0000000000..a651fba406 --- /dev/null +++ b/app/src/main/java/com/mogo/launcher/lancet/AsyncHandlerReflectLancet.java @@ -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> 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> 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> asyncHandlers = MainBlockCheck.Companion.getAsyncHandlers(); + asyncHandlers.add(new WeakReference<>(handler)); + return handler; + } else { + return new Handler(looper, callback); + } + } +} diff --git a/app/src/main/java/com/mogo/launcher/lancet/MainBlockCheck.kt b/app/src/main/java/com/mogo/launcher/lancet/MainBlockCheck.kt index 31214f5da5..3a8868bd92 100644 --- a/app/src/main/java/com/mogo/launcher/lancet/MainBlockCheck.kt +++ b/app/src/main/java/com/mogo/launcher/lancet/MainBlockCheck.kt @@ -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(128) + private const val TAG = "MAIN_BLOCK_CHECK" @JvmStatic - val whats by lazy { ConcurrentHashMap>() } + private val tokens = ArrayMap(128) + + private val pool by lazy { Executors.newFixedThreadPool(1) } + + val asyncHandlers by lazy { CopyOnWriteArraySet>() } + + private val asyncHandlersMap by lazy { ConcurrentHashMap() } + + private val whats by lazy { ConcurrentHashMap>() } @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() }.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() }.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() }.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() }.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() }.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() }.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() }.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() }.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() }.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() }.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) + } } } diff --git a/config.gradle b/config.gradle index a7fbb640ce..88234c9f03 100644 --- a/config.gradle +++ b/config.gradle @@ -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", diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/ObjectHashCodeUtils.java b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/ObjectHashCodeUtils.java index b860b5319e..e841673568 100644 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/ObjectHashCodeUtils.java +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/ObjectHashCodeUtils.java @@ -11,18 +11,41 @@ public class ObjectHashCodeUtils { private static final ConcurrentHashMap 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); + } }