Skip to content

v1.8.4

Choose a tag to compare

@Kilowatch Kilowatch released this 13 Aug 06:14
· 28 commits to main since this release

Added

  • A gear (Settings) icon in the top-right corner of the mobile main-screen toolbar, next to the "+" button. Tapping it opens Settings directly; it hides during edit mode and is registered in the icon-customization picker under the Utility category.

Fixed

  • Fixed SMB browsing stalls and reconnect prompts by closing each per-operation share handle, coalescing and caching both server-mode share discovery and access checks for ten minutes, retaining healthy pooled sessions for a ten-minute idle window instead of forcing a reconnect after one minute, and failing over silently dropped pooled sockets within eight seconds.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread parked inside the runtime's native-allocation registry notification while a RecyclerView measures its rows during a normal frame — e.g. top frame dalvik.system.VMRuntime.notifyNativeAllocationsInternal (the native method ART calls from VMRuntime.notifyNativeAllocation when the count of registered native allocations since the last GC crosses its threshold) under libcore.util.NativeAllocationRegistry.registerNativeAllocation, reached from a framework Paint.<init> (the tiny text-measurement Paint a TextView allocates every time it lays out) under android.text.Layout.<init>/BoringLayout.<init> under TextView.makeSingleLayoutmakeNewLayoutTextView.onMeasureView.measureLinearLayoutManager/RecyclerView.onLayout, reached from a frame-draw traversal (Choreographer.doFrameViewRootImpl.performTraversalsperformLayout) — reported from a vivo I2219, SDK 36, app 1.8.2-FOSS. notifyNativeAllocationsInternal is the runtime's bookkeeping for the global native-allocation counter and blocks when the heap is under pressure from concurrent native allocations — in the report a dozen DefaultDispatcher-worker-* threads were simultaneously inside the same native method doing Bitmap.createBitmap while Coil decodes AVIF/HEIF images (com.radzivon.bartoshyk.avif.coder.HeifCoder.decodeSampled) — so the >5 s block is a runtime/GC-side allocator stall the app cannot act on, and the main thread's own work is the µs-scale allocation of a text-measurement Paint, not app business logic. This is the notifyNativeAllocationsInternal-top variant of the already-filtered LineBreaker.nComputeLineBreaks-top RecyclerView text-layout report (filter 33), sampled one step into the runtime native-allocation registry instead of the line-break engine. The AnrWatchdogThread now treats a main-thread stack whose top frame is VMRuntime.notifyNativeAllocationsInternal (or the Java notifyNativeAllocation below it), with a NativeAllocationRegistry.registerNativeAllocation frame, a Paint.<init> frame reached from a TextView.makeNewLayout/makeSingleLayout/onMeasure text-layout path, an androidx.recyclerview.widget.* frame and a frame-draw dispatch (Choreographer.doFrame/ViewRootImpl.performLayout/performTraversals), and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread parked inside a blocking primitive (a lock, file/network/database I/O or binder frame), or reach the registry notification from app business logic that is NOT a Paint/text-measurement path inside a RecyclerView layout (e.g. the main thread itself allocating a large Bitmap, which surfaces as Bitmap.createBitmap below the registry frame), and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at the parcel-write entry of a device-vendor (OEM) binder call to its own "trancare assist" service, made from the frame-skip Choreographer hook the vendor ROM injects into the frame-rendering pipeline — e.g. Choreographer.doFramecom.transsion.hubcore.view.TranChoreographerImpl.skippedFrames (the same TECNO/Transsion ROM Choreographer hook as the already-filtered filter 21 ServiceManager-lookup and filter 28 Slog.e/Log.println_native reports) → com.transsion.hubsdk.trancare.trancareassist.ITranTrancareAssistManager$Stub$Proxy.compulateSkipperFrame (the vendor AIDL proxy dispatching skipped-frame data to the ROM's trancare service) → android.os.Parcel.writeInterfaceTokenandroid.os.Parcel.nativeWriteInterfaceToken (top frame) — reported from a TECNO TECNO KJ5, SDK 33, app 1.8.1-FOSS. The sampled frame is the vendor hook writing the parcel interface token at the very START of its binder call: nativeWriteInterfaceToken is a µs-scale in-memory parcel-buffer write that cannot by itself occupy the main thread for 5 s (the blocking transact() follows only after the parcel is fully written, so a sample caught here is by definition not inside the binder round-trip), and a thread genuinely parked inside a >5 s block cannot be processing a freshly dispatched vsync frame callback (Choreographer$FrameDisplayEventReceiver.run under Handler.handleCallback) at sample time — so the >5 s block occurred in a PREVIOUS main-looper message and this sample is the post-stall first frame after recovery, the same family as filters 10/20/21/22/28. The stack has zero za.kilowatch.ultimatefilemanager frames, and the vendor SDK's class names (com.transsion.*, injected by the TECNO ROM, not part of this app) are not platform-prefixed, so the pure-framework filter did not match. The AnrWatchdogThread now treats a main-thread stack whose top frame is android.os.Parcel.nativeWriteInterfaceToken/writeInterfaceToken, containing a com.transsion.hubcore.view.TranChoreographerImpl.skippedFrames frame, a com.transsion.hubsdk.trancare.trancareassist.-prefixed frame, a Choreographer.doFrame frame and a Handler.handleCallback frame, with no za.kilowatch.ultimatefilemanager frames, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic — an app frame on the stack, or a top frame that is not a Parcel writeInterfaceToken under the vendor's skippedFrames (e.g. the app's own AIDL binder call, which carries the app's generated $Stub$Proxy frame above the parcel write) — and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at the entry of the bundled-library view factory (LayoutInflater.Factory2.onCreateView) while the framework cold-starts an Activity and inflates its window/content layout — e.g. LanguageWelcomeActivity.onCreate<obfuscated AppCompat setContentView>PhoneWindow.getDecorViewinstallDecorgenerateLayoutDecorView.onResourcesLoadedLayoutInflater.inflatecreateViewFromTag<obfuscated Factory2>.onCreateView<obfuscated view inflater>.onCreateView (top frame; the AppCompat delegate / AppCompatViewInflater factory creating one view instance per layout tag, whose onCreateView/createView entry keeps its name because it overrides the framework LayoutInflater$Factory2 interface), under Activity.performCreateInstrumentation.callActivityOnCreateActivityThread.performLaunchActivity — reported from a TCL UnionTV, SDK 26, app 1.8.3-GOOGLE. The sampled frame is the view factory creating a single view for a tag during a one-time cold-start layout inflation — bounded allocation/class-loading/attribute-decode work that cannot by itself occupy the main thread for 5 s; the only app frame is the Activity's own onCreate lifecycle callback the framework invoked, so the >5 s block is the one-time framework-driven cold-start cost (class loading, resource decode, layout inflation) on a low-end device, which the app cannot act on — the same class as the bundled-library layout-inflation <init> (filter 34), Activity-onCreate constructor (42) and MaterialButton-inflate (11) cold-start filters, sampled one frame EARLIER than the view constructor, at the factory that creates it. The AnrWatchdogThread now treats a main-thread stack whose top frame is onCreateView on a non-platform, non-app (bundled-library) class, with a LayoutInflater.createViewFromTag frame, an Activity cold-start launch frame (Activity.performCreate/Instrumentation.callActivityOnCreate/ActivityThread.performLaunchActivity), only Activity-class app frames, and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic — a top frame that is not a bundled-library onCreateView under that chain (e.g. a lock, file I/O, or binder frame), an app frame that is not an Activity class (e.g. adapter bind code), a framework blocking primitive anywhere on the stack, or a Factory2.onCreateView reached from app business logic rather than a framework Activity cold-start launch — and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside a HONOR/Huawei vendor-framework class initializer while the main looper dispatches a framework message through the ROM's real-time-scheduling factory — e.g. top frame android.iawareperf.RtgSched.<clinit> (HONOR's "iaware" Real-Time Scheduling class loading for the first time, whose static initializer resolves the vendor's RT-sched configuration and can stall on a slow or busy HONOR device), under com.hihonor.common.HnFrameworkFactoryImpl.getHwRtgSchedImplandroid.common.HwFrameworkFactory.getHwRtgSchedInstance, reached from android.app.ActivityThread$H.handleMessage (the main looper dispatching an ActivityThread framework message) — reported from a HONOR PTP-N49, SDK 36, app 1.7.7-GOOGLE. The currently executing frame is the vendor ROM's own one-time class initializer (class loading / vendor service resolution) that the app cannot act on; the stack has zero za.kilowatch.ultimatefilemanager frames, and the only non-platform frame is the vendor's own com.hihonor.* factory — com.hihonor.common is injected by the HONOR ROM and is not platform-prefixed, so the pure-framework filter did not match. The AnrWatchdogThread now treats a main-thread stack whose top frame is <clinit> on an android.iawareperf.*/com.hihonor.* (HONOR/Huawei) class, containing a com.hihonor.* frame, a getHwRtgSched*/HwFrameworkFactory vendor factory frame and an ActivityThread$H.handleMessage frame, with no za.kilowatch.ultimatefilemanager frames, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic — an app frame on the stack, or a top frame that is not a HONOR/Huawei vendor <clinit> under that factory chain (e.g. a lock, file I/O, or binder frame) — and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the framework's window-transition inflation while the framework cold-starts an Activity and installs its decor — e.g. top frame android.transition.TransitionSet.<init> (the transition object constructor) under android.transition.TransitionInflater.createTransitionFromXml/inflateTransition, reached from com.android.internal.policy.PhoneWindow.getTransitioninstallDecorgetDecorView, called from the app Activity's own onCreate (StorageBrowserActivity.onCreate, via the AppCompat setContentView chain) under Activity.performCreateInstrumentation.callActivityOnCreateActivityThread.performLaunchActivity — reported from a ZTE Blade A3 2020, SDK 28, app 1.8.1-FOSS. The currently executing frame is the framework parsing the window's transition XML and constructing the Transition object graph — bounded, one-time cold-start work (class loading, resource decode, object construction) that cannot by itself occupy the main thread for 5 s; the only app frame is the Activity's own onCreate lifecycle callback the framework invoked, so the >5 s block is the one-time framework-driven cold-start cost on a low-end device, which the app cannot act on — the same class as the bundled-library layout-inflation <init> (filter 34), Activity-onCreate constructor (42) and view-factory (45) cold-start filters, but sampled inside a PLATFORM android.transition.* class rather than a bundled-library class. Platform classes would match the pure-framework filter only when there are no app frames; here the Activity's own onCreate is the single app frame, so the new filter is needed. The AnrWatchdogThread now treats a main-thread stack whose top frame is an android.transition.* frame, with a com.android.internal.policy.PhoneWindow decor-install frame (installDecor/getDecorView/getTransition), an Activity cold-start launch frame (Activity.performCreate/Instrumentation.callActivityOnCreate/ActivityThread.performLaunchActivity), only Activity-class app frames, and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic — a top frame that is not an android.transition.* frame under that decor-install chain (e.g. a lock, file I/O, or binder frame), an app frame that is not an Activity class (e.g. adapter bind code), or transition inflation reached from app business logic rather than a framework Activity cold-start launch — and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the app's per-button focus styling while it handles a TV D-pad key event — top frame android.widget.TextView.setTextColor (the framework's trivial text-color setter: a field assignment plus a bounded invalidate() when the color changes, µs-scale work that cannot by itself occupy the main thread for 5 s), reached from an R8-obfuscated focus-change listener (jm6.onFocusChange — the app's focus styling, e.g. the focused button's text turns yellow), under the framework focus-gain chain (View.handleFocusGainInternalTextView.onFocusChanged/View.onFocusChanged), reached from requestFocus called by an R8-obfuscated key handler (yl6.onKey) during a D-pad key-event dispatch (ViewRootImpl$ViewPostImeInputStage.processKeyEventdispatchKeyEvent) — reported from an SDMC TV Smart 4K BOX, SDK 30, app 1.8.0-GOOGLE. The sampled frame is bounded per-navigation focus styling that runs on every D-pad focus move, and the main thread is RUNNABLE, actively processing a freshly dispatched key event — a thread parked inside a >5 s block cannot be doing that, so the >5 s block is device-side slowness / CPU starvation on a low-end TV (the report's own DlnaSsdpListener, NanoHttpd Main Listener, pool-2-thread-1 and DefaultDispatcher-worker-* threads are all RUNNABLE, busy with DLNA/SSDP discovery and the HTTP file server, starving the main thread) or a post-stall sample of the backlog the main looper drains after a genuine stall. The AnrWatchdogThread now treats a main-thread stack whose top frame is TextView.setTextColor, reached from a non-platform onFocusChange listener under the framework focus-gain chain (View.handleFocusGainInternal/onFocusChanged) called from a requestFocus reached through a key-event dispatch (dispatchKeyEvent/processKeyEvent), with no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic — a top frame that is not the trivial setTextColor under that focus-gain chain (e.g. the focus-change listener body executing blocking work, a lock, file I/O, or binder frame), or a focus change not reached from a key-event dispatch — and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread parked inside the runtime's native-allocation registry notification while a click-triggered layout inflation builds a MaterialButton's ripple background drawable — e.g. top frame dalvik.system.VMRuntime.notifyNativeAllocationsInternal (the native method ART calls from VMRuntime.notifyNativeAllocation when the count of registered native allocations since the last GC crosses its threshold) under libcore.util.NativeAllocationRegistry.registerNativeAllocation, reached from android.graphics.Path.<init> (the Path a button's ripple/inset background drawable allocates while it is constructed) under the LayerDrawable/InsetDrawable/RippleDrawable background-construction chain, under View.setBackgroundDrawablecom.google.android.material.button.MaterialButton.setInternalBackgroundMaterialButton.<init>, reached from the bundled view factory com.google.android.material.theme.MaterialComponentsViewInflater during a LayoutInflater inflation (createViewFromTag/inflate) that an app click listener triggered (View.performClick) — reported from a vivo I2219, SDK 36, app 1.8.2-FOSS, the same device and session family as the notifyNativeAllocationsInternal-top RecyclerView text-layout report (filter 43), sampled at a button-background construction instead of a text-layout Paint. notifyNativeAllocationsInternal is the runtime's bookkeeping for the global native-allocation counter and blocks when the heap is under pressure from concurrent native allocations — in the report a dozen DefaultDispatcher-worker-* threads were simultaneously inside the same native method doing Bitmap.createBitmap while Coil decodes AVIF/HEIF images (com.radzivon.bartoshyk.avif.coder.HeifCoder.decodeSampled) — so the >5 s block is a runtime/GC-side allocator stall the app cannot act on, and the main thread's own work is the µs-scale allocation of a button-background Path, not app business logic. This is the MaterialButton-inflation variant of the notifyNativeAllocationsInternal-top filter (43), sampled while the framework inflates a button background instead of measuring text; the existing filter required a Paint.<init> under a TextView.makeNewLayout/onMeasure RecyclerView text-layout path plus a frame-draw dispatch, none of which appear on a click-inflated MaterialButton stack. The AnrWatchdogThread now treats a main-thread stack whose top frame is VMRuntime.notifyNativeAllocationsInternal (or the Java notifyNativeAllocation below it), with a NativeAllocationRegistry.registerNativeAllocation frame, an android.graphics.Path.<init> frame reached from an android.graphics.drawable.RippleDrawable/LayerDrawable button-background construction chain, a com.google.android.material.button.MaterialButton frame (<init>/setInternalBackground) reached from a MaterialComponentsViewInflater frame during a LayoutInflater inflation, and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread parked inside a blocking primitive (a lock, file/network/database I/O or binder frame), or reach the registry notification from app business logic that is NOT a Path-allocating MaterialButton background construction under the Material view factory (e.g. the main thread itself allocating a large Bitmap, which surfaces as Bitmap.createBitmap below the registry frame), and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread blocked inside a synchronous binder call made by a bundled Google Play module Handler message — the Firebase Analytics / Google Analytics Measurement dynamite module (com.google.android.gms.dynamite_measurementdynamite, whose classes are R8-obfuscated to short names such as m7.* inside the dynamically loaded module) — e.g. Handler.dispatchMessagem7.el.handleMessage (the Measurement module's own main-looper Handler receiving one of its messages) → m7.ei.cm7.er.bm7.ep.am7.es.mBinderProxy.transacttransactNative (top frame) — reported from a Xiaomi MiTV-AFMU0, SDK 34, app 1.8.3-GOOGLE. The >5 s block is the Google Play Services process's response latency to the Measurement module's synchronous binder transaction, which the app cannot act on; the stack has zero za.kilowatch.ultimatefilemanager frames — the binder call is dispatched by the module's OWN non-platform Handler message, not app business logic — so the pure-framework filter does not match (the module's obfuscated m7.* class names are not platform-prefixed), and this is the binder-round-trip counterpart of the already-filtered GMS Measurement Thread.<init> construction shape (filter 27). The AnrWatchdogThread now treats a main-thread stack whose top frame is BinderProxy.transact/transactNative, whose Handler.dispatchMessage frame's direct caller is a non-platform handleMessage (a bundled-library / Google Play module Handler), with no app frames anywhere, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic — an app frame anywhere on the stack, a binder call dispatched by a framework or app Handler (whose handleMessage is platform- or app-prefixed), or a binder call not reached from a Handler.dispatchMessage at all — and are still reported.