package com.mogo.launcher.lancet import android.app.* import android.content.* import android.graphics.* import android.os.* import android.os.Handler.Callback import android.util.* import android.view.* import androidx.annotation.* import androidx.core.os.HandlerCompat import androidx.core.util.Pools import com.knightboost.lancet.api.* import com.knightboost.lancet.api.Scope.ALL import com.knightboost.lancet.api.Scope.LEAF import com.knightboost.lancet.api.annotations.* import com.knightboost.lancet.api.annotations.Weaver import com.mogo.eagle.core.block.runtime.config.recorder.* import com.mogo.eagle.core.block.runtime.utils.TimeUtils.Companion.now 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.* import com.mogo.eagle.core.block.runtime.message.Message as Holder @Keep @Weaver @Group("main_block_check") class MainBlockCheck { companion object { private const val TAG = "MAIN_BLOCK_CHECK" @JvmStatic private val tokens = ConcurrentHashMap>(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>>() } private data class PoolAction(var type: Int, var what: Int, var holder: Holder?, var elapsedTime: Long = -1, var duration:Long = -1): Runnable { override fun run() { try { val h = holder if (type == 0 && h != null) { whats.getOrPut(what) { LinkedList>() }.add( WeakReference(h) ) getRecorder()?.insert(h) } if (type == 1) { val holders = whats.remove(what)?.mapNotNull { it.get() } if (!holders.isNullOrEmpty()) { getRecorder()?.remove(holders) } } if (type == 2 && h != null) { val what = h.what if (what != null) { whats.remove(what)?.removeAll { it.get() == h } } getRecorder()?.recycle(h.id, elapsedTime, duration) } } finally { reset() actionPool.release(this) } } fun reset() { type = -1 what = Int.MIN_VALUE holder = null elapsedTime = -1 duration = -1 } } private val actionPool by lazy { Pools.SynchronizedPool(500) } private fun getAction(): PoolAction = actionPool.acquire() ?: PoolAction(-1, 0, null) @JvmStatic fun getRecorder(): IMessageRecorder? { val block = CallerDevaToolsManager.block() if (block == null || !block.hasInit()) { return null } return block.recorder() } @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() val elapsedTime = now - enclose.enqueueTime try { if (action != null) { action.run() } else { if (oldMsg == null) { h?.dispatchMessage(msg) } else { oldMsg.obj = oldObj h?.dispatchMessage(oldMsg) } } } finally { val duration = now() - now recycle(enclose, 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") @ReplaceInvoke fun handlerPostProxy(handler: Handler, action: Runnable): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.post(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(newHandler, action = action, isAsync = isAsync) msg.obj = holder val inserted = newHandler.sendMessage(msg) if (inserted) { insert(what, holder) } return inserted } @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 isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) } val newHandler = getHandler(isAsync) val msg = Message.obtain(newHandler) val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action) msg.what = what val holder = Holder.acquire(handler, action = action, delay = delayMillis, isAsync = isAsync) msg.obj = holder val inserted = newHandler.sendMessageDelayed(msg, delayMillis) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "postAtTime") @ReplaceInvoke fun handlerPostDelayProxy2(handler: Handler, action: Runnable, token: Any?, delayMillis: Long): Boolean { if (Looper.getMainLooper() != handler.looper) { return HandlerCompat.postDelayed(handler, action, token, delayMillis) } val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) } val newHandler = getHandler(isAsync) val msg = Message.obtain(newHandler) val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action) msg.what = what val holder = Holder.acquire(handler, action = action, delay = delayMillis, obj = token) msg.obj = holder if (token != null) { synchronized(tokens) { tokens[token.hashCode()] = WeakReference(holder) } } val inserted = HandlerCompat.postDelayed(newHandler, action, token, delayMillis) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "postAtFrontOfQueue") @ReplaceInvoke fun handlerPostAtFrontOfQueueProxy(handler: Handler, action: Runnable): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.postAtFrontOfQueue(action) } val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) } val newHandler = getHandler(isAsync) val msg = Message.obtain(newHandler) val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action) msg.what = what val holder = Holder.acquire(handler, action = action) msg.obj = holder val inserted = newHandler.sendMessageAtFrontOfQueue(msg) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "postAtTime") @ReplaceInvoke fun handlerPostAtTimeProxy(handler: Handler, action: Runnable, uptimeMillis: Long): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.postAtTime(action, uptimeMillis) } val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) } val newHandler = getHandler(isAsync) val msg = Message.obtain(newHandler) val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action) msg.what = what val delta = uptimeMillis - SystemClock.uptimeMillis() val holder = Holder.acquire(handler, action = action, delay = if (delta > 0) delta else 0) msg.obj = holder val inserted = newHandler.sendMessageAtTime(msg, uptimeMillis) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "postAtTime") @ReplaceInvoke fun handlerPostAtTimeProxy2(handler: Handler, action: Runnable, token: Any?, uptimeMillis: Long): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.postAtTime(action, uptimeMillis) } val isAsync = asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) } val newHandler = getHandler(isAsync) val msg = Message.obtain(newHandler) val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action) msg.what = what val delta = uptimeMillis - SystemClock.uptimeMillis() val holder = Holder.acquire(handler, action = action, delay = if (delta > 0) delta else 0, obj = token) msg.obj = holder if (token != null) { synchronized(tokens) { tokens[token.hashCode()] = WeakReference(holder) } } val inserted = newHandler.sendMessageAtTime(msg, uptimeMillis) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "sendEmptyMessage") @ReplaceInvoke fun handlerSendEmptyMessage(handler: Handler, what: Int): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.sendEmptyMessage(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 = newHandler.sendMessage(msg) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "sendEmptyMessageAtTime") @ReplaceInvoke fun handlerSendEmptyMessageAtTime(handler: Handler, what: Int, uptimeMillis: Long): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.sendEmptyMessageAtTime(what, 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 = newHandler.sendMessageAtTime(msg, uptimeMillis) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "sendEmptyMessageDelayed") @ReplaceInvoke fun handlerSendEmptyMessageDelayed(handler: Handler, what: Int, delayMillis: Long): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.sendEmptyMessageDelayed(what, 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 = newHandler.sendMessageDelayed(msg, delayMillis) if (inserted) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "sendMessage") @ReplaceInvoke fun handlerSendMessage(handler: Handler, msg: Message): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.sendMessage(msg) } 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 newMsg.obj = obj if (oldObj != null) { synchronized(tokens) { tokens[oldObj.hashCode()] = WeakReference(obj) } } val inserted = newHandler.sendMessage(newMsg) if (inserted) { insert(newMsg.what, obj) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "sendMessageAtTime") @ReplaceInvoke fun handlerSendMessageAtTime(handler: Handler, msg: Message, uptimeMillis: Long): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.sendMessageAtTime(msg, 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 newMsg.obj = obj if (oldObj != null) { synchronized(tokens) { tokens[oldObj.hashCode()] = WeakReference(obj) } } val inserted = newHandler.sendMessageAtTime(newMsg, uptimeMillis) if (inserted) { insert(newMsg.what, obj) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "sendMessageAtFrontOfQueue") @ReplaceInvoke fun handlerSendMessageAtFrontOfQueue(handler: Handler, msg: Message): Boolean { if (Looper.getMainLooper() != handler.looper) { return handler.sendMessageAtFrontOfQueue(msg) } 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 newMsg.obj = obj if (old != null) { synchronized(tokens) { tokens[old.hashCode()] = WeakReference(obj) } } val inserted = newHandler.sendMessageAtFrontOfQueue(newMsg) if (inserted) { insert(newMsg.what, obj) } return inserted } @JvmStatic @TargetClass(value = "android.app.Activity", scope = ALL) @TargetMethod(methodName = "post") @ReplaceInvoke fun runOnUiThreadOfActivityProxy(activity: Activity, action: Runnable) { val msg = Message.obtain() val what = ObjectHashCodeUtils.getHashCodeIfNeed(activity, action) msg.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) { insert(what, holder) } } @JvmStatic @TargetClass(value = "android.view.View", scope = ALL) @TargetMethod(methodName = "post") @ReplaceInvoke fun postOfViewProxy(view: View, action: Runnable): Boolean { val msg = Message.obtain() val what = ObjectHashCodeUtils.getHashCodeIfNeed(view, action) msg.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) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.view.View", scope = ALL) @TargetMethod(methodName = "postDelayed") @ReplaceInvoke fun postDelayedOfViewProxy(view: View, action: Runnable, delayMillis: Long): Boolean { val msg = Message.obtain() val what = ObjectHashCodeUtils.getHashCodeIfNeed(view, action) msg.what = what 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) { insert(what, holder) } return inserted } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "removeCallbacks") @ReplaceInvoke fun handlerRemoveCallbacks(handler: Handler, action: Runnable) { if (Looper.getMainLooper() != handler.looper) { return handler.removeCallbacks(action) } val what = ObjectHashCodeUtils.getHashCodeIfNeed(handler, action) getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what) remove(what) } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "removeCallbacks") @ReplaceInvoke fun handlerRemoveCallbacksWithToken(handler: Handler, action: Runnable, token: Any?) { if (Looper.getMainLooper() != handler.looper) { 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) remove(what) } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "removeMessages") @ReplaceInvoke fun handlerRemoveMessages(handler: Handler, what: Int) { if (Looper.getMainLooper() != handler.looper) { return handler.removeMessages(what) } getHandler(asyncHandlersMap.getOrPut(handler.hashCode()) { computeIsAsyncHandler(handler) }).removeMessages(what) remove(what) } @JvmStatic @TargetClass(value = "android.view.View", scope = ALL) @TargetMethod(methodName = "removeCallbacks") @ReplaceInvoke fun viewRemoveCallback(view: View, action: Runnable): Boolean { val what = ObjectHashCodeUtils.getHashCodeIfNeed(view, action) HANDLER.removeMessages(what) remove(what) return true } @JvmStatic @TargetClass(value = "android.os.Handler", scope = ALL) @TargetMethod(methodName = "removeMessages") @ReplaceInvoke fun handlerRemoveMessagesWithToken(handler: Handler, what: Int, token: Any?) { 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) remove(what) } private fun computeIsAsyncHandler(handler: Handler): Boolean { return asyncHandlers.find { it.get() === handler } != null } fun insert(what: Int, holder: Holder) { 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) } 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 { return if (isAsync) { ASYNC_HANDLER } else { HANDLER } } } @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) } } @TargetClass(value = "android.app.Activity", scope = LEAF) @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) } } @TargetClass(value = "android.app.Activity", scope = LEAF) @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) } } }