Added
- Native AVIF image decoding support (
org.aomedia.avif.android:avif1.3.0) in the built-in image viewer and thumbnail generator for API levels 26–30, with systemImageDecoderhardware acceleration on API 31+. - Option in mobile settings to tap folder or file icons in list view to enter edit/selection mode (enabled by default).
- Multi-format compression support for
.tar,.tar.gz,.tar.bz2,.tar.xz,.tar.zst,.gz,.bz2,.xz, and.zst. - Modern checkable format toggle pills (
ChipGroup) in the Compression dialog for Mobile and Android TV. - Extraction support and conflict/collision handling for
.tar,.tar.gz,.tar.bz2,.tar.xz,.tar.zst,.rar,.gz,.bz2,.xz, and.zst. - Universal archive entry viewing, single-entry extraction, moving out, and deletion for ZIP, 7Z, and TAR-compressed streams (
.tar,.tar.gz,.tar.bz2,.tar.xz,.tar.zst,.gz,.bz2,.xz,.zst). - Network & Cloud share "Extract Here" support for SMB, FTP, SFTP, NFS, and Cloud storage targets.
- Flexible Batch Rename patterns with token support (
#/##/###,$F/$fullname,$N/$name,$E/$ext, date tokens$Y,$M,$D, and case transform tokens$U/$upper,$L/$lower). - Standalone Extension (
$E) toggle pill with dedicated custom extension input field (csv→photo.csv). - Two-way checkable toggle chips helper panel for pattern insertion & auto-syncing on Mobile and Android TV.
- Pattern Tokens Help (
?) toolbar button with token reference guide & examples on Mobile and Android TV.
Changed
-
Tapping a folder or file icon in list view on mobile now enters selection mode when enabled.
-
Compression dialog dynamically hides password protection fields for archive formats that do not support encryption.
-
Set "Extract Here" to FAB Tools bottom sheet on Mobile and top action bar on Android TV.
-
Updated
$Ntoken to output strictly bare filename without extension (photo). -
Removed parenthesis wrapping from
{Padding}token output in Batch Rename.
Fixed
- Fixed AVIF and HEIC/HEIF thumbnails not rendering when browsing network or online shares (SMB, FTP, SFTP, NFS, Cloud, WebDAV, DLNA) due to missing image extension filters and lack of AVIF stream decoding in
NetworkThumbnailCacheManager. - Updated category filters, Smart Sort, file tags, file properties, recycle bin, file indexing, and network MIME type mapping to recognize
.avifimage files. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the super-constructor chain of an Activity while the framework cold-starts that Activity — top frame
<obfuscated lifecycle owner>.getLifecycle(a trivial field-returning getter), underComponentActivity.<init>→FragmentActivity.<init>→AppCompatActivity.<init>→LanguageWelcomeActivity.<init>→Class.newInstance→AppComponentFactory.instantiateActivity/Instrumentation.newActivity→ActivityThread.performLaunchActivity— reported from a SEI Robotics Movix Pro, SDK 28, app 1.8.0-GOOGLE. The currently executing frame isgetLifecycle(), which just returns the lifecycle-owner's registry field and cannot by itself occupy the main thread for 5 s; the only app frame is the launching Activity's own<init>(its constructor body has not even run —super()is still in progress), so the >5 s block is the one-time framework-driven cold-start cost (class loading, resource decode) on a low-end device, which the app cannot act on. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isgetLifecycle, with aClass.newInstanceframe and a framework Activity-launch frame (AppComponentFactory.instantiateActivity/Instrumentation.newActivity/ActivityThread.performLaunchActivity), where everyza.kilowatch.ultimatefilemanagerframe is an Activity<init>constructor, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes that keep the main thread inside app business logic — the top frame is notgetLifecycle, or the Activity's own constructor (or a helper it constructs) is executing blocking work — are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at
java.lang.StringBuilder.appendone instruction deeper inside the same freshly dispatched main-looper Runnable — top frameStringBuilder.appendwith aStringBuilder.<init>frame directly below it (theStringBuilder(String)constructor invokesappendinternally, so the wholeappend→<init>pair is still the freshly entered Runnable's first statement), then a non-platformrun()andHandler.handleCallbackbeneath — reported from a Google Pixel 6a, SDK 37, app 1.7.6. This is the same post-stall sampling artifact as the previously-filteredStringBuilder.<init>-top and directStringBuilder.append-top shapes, sampled one instruction further inside the constructor's own append call: a StringBuilder construction plus an O(n) buffer copy cannot by themselves occupy the main thread for 5 s, and the frame sits directly under a Runnable just entered via the main Handler, so the >5 s block occurred in a PREVIOUS main-looper message and this sample is post-stall backlog whose top frame is harmless string construction, not the freeze itself. TheAnrWatchdogThreadnow treats a main-thread stack whose top frames areStringBuilder.append→StringBuilder.<init>→ non-platformrun()→Handler.handleCallback— in addition to the existing shapes where a singleStringBuilder.<init>/appendframe sits directly above therun()— as a post-stall sampling artifact and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside the blocking work — the top frame is not a trivial StringBuilder<init>/appenddirectly under a Runnable just entered viaHandler.handleCallback— and are still reported. - Fixed an ANR (App Freeze) when stopping the embedded FTP or SFTP server from the notification's Stop action, the Server Host screen, or the FTP/SFTP toggle tiles/widgets — reported from an SDMC TV Smart 4K BOX, SDK 30, app 1.8.0-GOOGLE.
FileServerService.onStartCommand(which runs on the main thread) calledUfmFtpServer.stop()synchronously; Apache FtpServer'sDefaultFtpServer.stop()→NioListener.stop()→ Apache MinaAbstractIoAcceptor.unbind()waits onDefaultIoFuture.await0(anObject.wait) for the acceptor/IO processor to finish unbinding, which exceeds the 5 s watchdog threshold when it is busy tearing down (e.g. active sessions). FTP and SFTP shutdown is now dispatched to a dedicated background scope (serverStopScope, a never-cancelledDispatchers.IOscope kept separate fromserviceJob), soonStartCommand/onTaskRemoved/onDestroynever block the main thread; the DLNA/renderer stops were moved onto the same scope and the now-redundant stop wrappers were removed so a cancelledserviceJobcan never cancel an in-flight server stop. Server connect/auth/transfer behaviour is unchanged. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside a trivial view lookup while an Activity's own
onCreateruns during a framework-driven cold-start Activity launch — e.g.SafPickerActivity.onCreate→setupViews()→<obfuscated helper>.findViewById(top frame), underActivity.performCreate→Instrumentation.callActivityOnCreate→ActivityThread.performLaunchActivity(reported from an onn Streaming Device 4K pro, SDK 34, app 1.7.7). The stack has exactly one app frame — the Activity's ownonCreatelifecycle callback the framework invoked — and the currently executing frame isfindViewById, an O(view-tree depth) lookup that cannot by itself occupy the main thread for 5 s; the >5 s block is the framework-driven launch itself (cold-start class loading, layout inflation and resource decode on a low-end device, with the report's own background threads — SSDP/DLNA discovery, SQLite, Netty event loops — RUNNABLE and starving the main thread), which the app cannot act on. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isfindViewById, with exactly one app frame that is an Activity's ownonCreateand a framework Activity-launch frame (Instrumentation.callActivityOnCreate/Activity.performCreate) 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 notfindViewById, more than one app frame, or the Activity'sonCreateitself executing the blocking work (a lock, I/O, or binder) — and are still reported. - Fixed a false-positive ANR (App Freeze) report when the main thread is blocked on a synchronous binder call to the system server's ActivityTaskManager while the app launches an Activity — e.g.
LanguageWelcomeActivity.onCreate→Activity.startActivity→startActivityForResult→Instrumentation.execStartActivity→IActivityTaskManager$Stub$Proxy.startActivity→BinderProxy.transact→transactNative(top frame) — reported from a Xiaomi MiTV-AFMU0, SDK 34, app 1.8.0-GOOGLE. The app merely invoked the one-line framework APIstartActivity(); the >5 s block is the system server's response latency to the activity-launch transaction, which the app cannot act on. The top frame is the binder transact into the system server — the app is inside the round-trip, not executing business logic — so even though the stack carries the launching Activity's ownonCreatecall-path frame (the onCreate decided to launch the next screen), the wait is still system-side, the same class as the existingunbindServicebinder filter. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isBinderProxy.transact/transactNativewith anIActivityTaskManager$Stub$Proxy.startActivityframe as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes that run app business logic have an app frame as the current frame (the top frame is notBinderProxy.transact/transactNative) and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the recursive
calcMaxmax-walk of the same frameworkSpannableStringBuilderspan-removal bookkeeping — top frameandroid.text.SpannableStringBuilder.calcMax(a recursionrestoreInvariantsruns to re-establish the span-order invariant after removing a span, reached viaSpannableStringBuilder.removeSpan) — while a main-looper Runnable is being dispatched, with a non-platformrun()frame sitting directly onHandler.handleCallback(reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filteredSpannableStringBuilder.removeSpan/restoreInvariants,IdentityHashMap.get,View.invalidate,MeasuredText, andnDrawTextRunreports). This is the identical span-removal chain as the previously-filteredremoveSpan-top andIdentityHashMap.get-top shapes, sampled one frame further:calcMax's recursion depth is bounded by the fixed number of span buckets and the total walk stays bounded by the span count (search highlights are scoped to the currently loaded text page; syntax highlighting is capped at the edit-mode size limit), so neither the walk nor the max-calc can by itself occupy the main thread for 5 s; the >5 s block is device-side slowness / CPU starvation or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadspan-removal filter now also treats a main-thread stack whose top frame isSpannableStringBuilder.calcMax, with aSpannableStringBuilder.restoreInvariantsframe and aSpannableStringBuilder.removeSpanframe, dispatched from a main-looper Runnable (Handler.handleCallbackdirectly below a non-platformrun()frame), as a false positive and resets its heartbeat instead of writing a report. Genuine freezes that keep the main thread inside heavy app span work reach the builder from app business logic WITHOUT aHandler.handleCallbackmessage-dispatch frame on the stack (the app callssetSpan/removeSpandirectly, e.g. from the search-highlight path or adapter bind code, not from a Runnable just dispatched by the main Handler) and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at the entry of a freshly dispatched main-looper Runnable — top frame
ne2.run(a non-platform, R8-obfuscatedrun()method) sitting directly onandroid.os.Handler.handleCallback— reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filteredMeasuredText,nDrawTextRun,SpannableStringBuilder.removeSpanandView.invalidatereports. The sampled Runnable was just entered — itsrun()is the TOP frame withHandler.handleCallbackdirectly below it and no deeper frames, so the main looper is demonstrably processing messages at sample time, which a thread parked inside a >5 s block cannot do; the >5 s block occurred in a PREVIOUS main-looper message and this sample is the post-stall backlog the looper drains after recovery — the same family as theStringBuilder.<init>/appendpost-stall artifacts, just sampled one frame earlier at the Runnable's own entry. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame is a non-platformrun()directly underHandler.handleCallback(with noHandler.postDelayedframe) as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside the blocking work — the top frame is NOT a barerun()entry directly onHandler.handleCallback(it is a deeper blocking frame such as a lock, file I/O, or binder call) — and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread one instruction deeper inside the same framework
SpannableStringBuilderspan-removal bookkeeping — top framejava.util.IdentityHashMap.get(the insertion-order-map lookup/update insiderestoreInvariants' bounded span-order walk, reached viaSpannableStringBuilder.removeSpan) — while a main-looper Runnable is being dispatched, with a non-platformrun()frame sitting directly onHandler.handleCallback(reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filteredSpannableStringBuilder.removeSpan/restoreInvariants,MeasuredText,nDrawTextRun, andView.invalidatereports). This is the identical span-removal chain as the previously-filteredremoveSpan-top shape, sampled one frame further —restoreInvariantsre-establishes the sorted-order invariant by walking the builder's span array and doing an O(1)IdentityHashMaplookup/update per span (search highlights are scoped to the currently loaded text page; syntax highlighting is capped at the edit-mode size limit), so neither the walk nor the map call can by itself occupy the main thread for 5 s; the >5 s block is device-side slowness / CPU starvation or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadspan-removal filter now also treats a main-thread stack whose top frame isIdentityHashMap.get/put, with aSpannableStringBuilder.restoreInvariantsframe and aSpannableStringBuilder.removeSpanframe, dispatched from a main-looper Runnable (Handler.handleCallbackdirectly below a non-platformrun()frame), as a false positive and resets its heartbeat instead of writing a report. Genuine freezes that keep the main thread inside heavy app span work reach the builder from app business logic WITHOUT aHandler.handleCallbackmessage-dispatch frame on the stack (the app callssetSpan/removeSpandirectly, e.g. from the search-highlight path or adapter bind code, not from a Runnable just dispatched by the main Handler) and are still reported. - Fixed an ANR (App Freeze) during cold app startup on low-end Android TV devices (e.g. onn Full HD Streaming Device, SDK 34, app 1.7.8-GOOGLE) caused by a synchronous system-server binder call on the main thread:
UfmApplication.onCreate→ConnectivityManager.registerDefaultNetworkCallback()→IConnectivityManager$Stub$Proxy.requestNetwork→BinderProxy.transact→transactNative(top frame). The app registered its Wi-Fi transition listener — theNetworkCallbackthat purges pooled SMB sessions when the device switches networks — synchronously at the end ofApplication.onCreate().registerDefaultNetworkCallbackis a blocking binder round-trip to the system server'sIConnectivityManager, and on a slow or busy box that single call exceeded the 5 s watchdog threshold while the user was still on the launcher, freezing cold startup and tripping the ANR. The registration now runs on a dedicated background daemon thread (ufm-net-callback, background priority).NetworkCallbackcallbacks are delivered on the ConnectivityThread, not the registering thread, so SMB pool purging on Wi-Fi transitions is unchanged — but the main thread no longer performs any binder work duringonCreate, so cold startup can't stall on the system server's response latency. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at
android.view.View.invalidatewhile a TextView invalidates itself after a framework span-removal — top frameView.invalidate, underTextView.spanChange→TextView$ChangeWatcher.onSpanRemoved→SpannableStringBuilder.sendSpanRemoved/removeSpan/restoreInvariants, reached from the same main-looper Runnable dispatch (a non-platformrun()frame sitting directly onHandler.handleCallback) — reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filteredMeasuredText,nDrawTextRun, andSpannableStringBuilder.removeSpanreports. This is the identical span-removal chain as the previously-filtered removeSpan-top shape, just sampled one step further — the TextView marking itself dirty (View.invalidateis an O(1) flag set) after the removal's change notification has already walked the bounded span array (search highlights are scoped to the currently loaded text page; syntax highlighting is capped at the edit-mode size limit), so it cannot by itself occupy the main thread for 5 s; the >5 s block is device-side slowness / CPU starvation or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadspan-removal filter now treats a main-thread stack whose top frame isView.invalidate, with aTextView.spanChangeframe, aTextView$ChangeWatcher.onSpanRemovedframe, and aSpannableStringBuildersendSpanRemoved/removeSpan/restoreInvariantsframe, dispatched from a main-looper Runnable (Handler.handleCallbackdirectly below a non-platformrun()frame), as a false positive and resets its heartbeat instead of writing a report. Genuine freezes that keep the main thread inside heavy app span work reach the builder from app business logic WITHOUT aHandler.handleCallbackmessage-dispatch frame on the stack (the app callssetSpan/removeSpandirectly, e.g. from the search-highlight path or adapter bind code, not from a Runnable just dispatched by the main Handler) and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the framework's native text measurement while an EditText processes a character committed by the IME — top frame
android.graphics.text.MeasuredText$Builder.nBuildMeasuredText/build, underMeasuredParagraph.buildForStaticLayout→StaticLayout.generate→DynamicLayout.reflow/DynamicLayout$ChangeWatcher.reflow, reached from the IME text-input path (BaseInputConnection.replaceText→ the editable'sreplace→SpannableStringBuilder.replace→sendTextChanged→ the TextView's watcher chain) — reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filterednDrawTextRunandSpannableStringBuilder.removeSpanreports. This is the normal framework text-layout work that runs every time the user types into any EditText: the only non-platform frames on the stack are the framework's own text-change notification chain (the TextView's TextWatcheronTextChangedcallbacks and the emoji-aware editable wrapper, e.g.androidx.emoji2.text.SpannableBuilder, that the IME edits through), not heavy app business logic — the app merely runs its standard edit path, and the Text Viewer/Editor's edit mode is already capped at 128 KB, so the measurement is bounded and cannot by itself hold the main thread for 5 s on a normally-provisioned device; the >5 s block is device-side slowness / CPU starvation on a very low-end device. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isMeasuredText$Builder.nBuildMeasuredText/build, with aDynamicLayout.reflow/DynamicLayout$ChangeWatcher.reflowframe and aBaseInputConnection.replaceTextframe, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes that keep the main thread inside app business logic — the top frame is not the native measurement, or the reflow is not reached from an IME text edit (noBaseInputConnection.replaceTextframe, e.g. the app callssetText/appenddirectly) — are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at
java.lang.StringBuilder.append— one instruction past the already-filteredStringBuilder.<init>— directly under an obfuscated app/libraryrun()dispatched byHandler.handleCallback(reported from an Innopia MundoGoTV, SDK 34, app 1.7.7). A singleappendof an already-resolved string is an O(n) buffer copy that cannot by itself occupy the thread for 5 s, and the frame sits directly under a Runnable just entered via the main Handler (the direct caller of the append is the Runnable itself, withHandler.handleCallbackone frame below it), so it is the same post-stall sampling artifact as the constructor variant: the >5 s block occurred in a PREVIOUS main-looper message and this sample is post-stall backlog whose top frame is harmless string construction, not the freeze itself. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isStringBuilder.append— in addition to the existingStringBuilder.<init>— whose second frame is a non-platformrun(), and whose third frame isHandler.handleCallback, as a post-stall sampling artifact and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside the blocking work — the top frame is not a trivial StringBuilder<init>/appenddirectly under a Runnable just entered viaHandler.handleCallback— and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at the constructor of WorkManager's
SystemJobService— top frameandroidx.work.impl.background.systemjob.SystemJobService.<init>— while the framework creates the service on the main thread (reported from a TCL Smart TV Pro, SDK 34, app 1.7.6). This is the same framework-driven service instantiation as the previously-fixedSystemJobService.<clinit>shape —ActivityThread.handleCreateService→AppComponentFactory.instantiateService→Class.newInstance— just sampled one frame further into the same one-time class-loading/construction cost on a slow or busy device: the stack has zeroza.kilowatch.ultimatefilemanagerframes, so the app cannot act on it. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame is a bundled-library<init>— in addition to the existing<clinit>— during framework service instantiation (aClass.newInstanceframe plus anAppComponentFactory.instantiateService/ActivityThread.handleCreateServiceframe, and no app frames) as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep an app frame on the stack — including an app Service's own<init>, whose class name starts with the app package — and are still reported. - Fixed a crash (
java.lang.OutOfMemoryError) when Smart Sort moved a large file across storage types (or after a failed same-volume rename) on low-memory devices (e.g. AMLOGIC TX100 PRO, SDK 28, app 1.7.7).SmartSortEngine.moveFileread the entire file into aByteArraybefore writing it to the destination (File.readBytes()for local sources, aByteArrayOutputStreamfor network sources); a file of ~313 MB produced a single 328,791,528-byte allocation that exceeds the device's 256 MB heap growth limit, crashing the app. Smart Sort is launched from alifecycleScope.launch(Main.immediate) aroundengine.execute, so the uncaught OOM surfaced on the main thread. Smart Sort moves now stream the copy in 256 KB chunks:SmartSortStorage.writeBytes(path, ByteArray)was replaced withwriteStream(path, input, size),moveFileopens the source as anInputStream(aFileInputStreamfor local sources, the share client's input stream for network sources), and the destination is written via the share client's streaminguploadStream(FTP/OneDrive/TV/Google Drive/Dropbox/WebDAV/S3) or a chunkedcopyTooutput stream (SMB/SFTP/SCP/NFS). The zero-byte guard still verifies the destination before the source is deleted, and a move is only blocked when the source size cannot be determined at all — empty files still move. Peak memory for a Smart Sort move is now bounded to the 256 KB copy buffer regardless of file size. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside a framework
SpannableStringBuilderspan bookkeeping operation — top frameandroid.text.SpannableStringBuilder.restoreInvariants/removeSpan(removing a single span walks the builder's span array, shifts the entries and re-establishes the sorted-order invariant) — while a main-looper Runnable is being dispatched, with a non-platformrun()frame sitting directly onHandler.handleCallback(reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS). A single span removal is bounded by the number of spans the app places on the text (search highlights are scoped to the currently loaded text page; syntax highlighting is capped at the edit-mode size limit), so it cannot by itself occupy the main thread for 5 s; the >5 s block is device-side slowness / CPU starvation or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isSpannableStringBuilder.removeSpan/restoreInvariants, dispatched from a main-looper Runnable (Handler.handleCallbackdirectly below a non-platformrun()frame), as a false positive and resets its heartbeat instead of writing a report. Genuine freezes that keep the main thread inside heavy app span work reach the builder from app business logic WITHOUT aHandler.handleCallbackmessage-dispatch frame on the stack (the app callssetSpan/removeSpandirectly, e.g. from the search-highlight path or adapter bind code, not from a Runnable just dispatched by the main Handler) and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the framework's text-drawing path for an editable TextView (EditText) while a normal frame is being drawn — top frame
android.graphics.BaseRecordingCanvas.nDrawTextRun/drawTextRun, underandroid.text.Layout.drawText→Editor.drawHardwareAcceleratedInner→Editor.onDraw→TextView.onDraw, dispatched fromChoreographer.doFrame/ViewRootImpl.performDraw(reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS). The stack is the Text Viewer/Editor's content EditText (activity_text_viewer.xml: ConstraintLayout → ScrollView → HorizontalScrollView → EditText,wrap_content, SPANNABLE buffer), butTextView.onDrawonly draws the line range that intersects the viewport, so the drawing work is bounded by the visible lines and cannot by itself occupy the main thread for 5 s. The stack has zeroza.kilowatch.ultimatefilemanagerframes — the only non-platform frame is the AndroidXConstraintLayout.dispatchDrawin the draw chain, which breaks the pure-framework filter but is a bundled-library view-layout frame, not app business logic — so the >5 s block is device-side slowness / CPU starvation, or a post-stall sample (the Choreographer frame callback is an async message the main looper can process ahead of the overdue sync heartbeat ticker after a stall, leavingtickerJustRanfalse). TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isBaseRecordingCanvas.nDrawTextRun/drawTextRun, with aTextView.onDrawframe, anEditorframe (onDraw/drawHardwareAccelerated/drawHardwareAcceleratedInner), aLayout.drawTextframe, a frame-draw dispatch frame (Choreographer.doFrame/ViewRootImpl.performDraw), and noza.kilowatch.ultimatefilemanagerframes, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep an app frame on the stack — app business logic on the main thread, or a custom view whose ownonDrawperforms heavy text drawing (its app class frame appears on the stack) — and are still reported. - Fixed a crash (
java.lang.RuntimeException:android.os.TransactionTooLargeException, data parcel size ~524 KB) when an Activity stops while the Batch Rename bottom sheet is open on a large file selection — reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS.BatchRenameDialogFragment.newInstance(...)passed the entire selected-files list through fragmentarguments(putParcelableArray("items", ...)); fragmentargumentsare re-serialized into the host Activity's saved-instance-state parcel on everyonSaveInstanceState, and when thousands of files are selected (e.g. "Select All" in a big folder) that bundle exceeded the Binder transaction limit the moment the Activity stopped, crashing atandroid.app.ActivityClient.activityStopped. The items now travel through an in-memoryBatchRenameItemsCache(the same pattern already used for media playlists) and only a small cache-key string goes into fragmentarguments; the dialog peeks the list back inonCreateand releases the entry when it is truly finished (kept across configuration changes so rotation still works). Batch Rename behaviour is unchanged — the same files, preview, and rename flow. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside WorkManager's
SystemJobServicewhile the system's JobScheduler starts a scheduled job — top framerr9.hashCode()(the R8-obfuscated WorkManager-internal type used as the active-jobs map key), underHashMap.hash/HashMap.put, underandroidx.work.impl.background.systemjob.SystemJobService.onStartJob, dispatched byJobServiceEngine$JobHandler.handleMessage(reported from a Google Pixel 6a, SDK 37, app 1.7.6). JobScheduler delivers job callbacks on the main thread, andonStartJobinserts the fired job into WorkManager's active-jobs HashMap — O(1) bounded bookkeeping that cannot by itself occupy the main thread for 5 s; the >5 s block is device-side slowness / CPU starvation (the report'sWM.task-1thread was RUNNABLE, busy in a background WorkManager task) or a post-stall sample. The stack has zeroza.kilowatch.ultimatefilemanagerframes — the current frame is WorkManager library bookkeeping the app cannot act on, and UFM's own workers (Advanced Sync, instant sync, etc.) run on WorkManager's background executor, never insideonStartJob. TheAnrWatchdogThreadnow treats a main-thread stack that contains aSystemJobService.onStartJobframe, aJobServiceEngine$JobHandler.handleMessageframe, and noza.kilowatch.ultimatefilemanagerframes, whose top frame is ahashCode()/HashMap.hash/HashMap.put/HashMap.putVal— i.e. the job-start HashMap insertion — as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep an app frame on the stack and are still reported. - Fixed a false-positive ANR (App Freeze) report when the main thread is blocked on a synchronous binder call to the system server's ServiceManager made by a device-vendor HubSDK hook injected into the frame-rendering pipeline — e.g.
Choreographer.doFrame→com.transsion.hubcore.view.TranChoreographerImpl.skippedFrames(TECNO's ROM-installed Choreographer hook) →com.transsion.hubsdk.trancare.trancareassist.TranTrancareAssistManager.getService→TranServiceManager.getServiceIBinder→ServiceManager.getService→IServiceManager$Stub$Proxy.checkService→BinderProxy.transact→transactNative(top frame) — reported from a TECNO TECNO KL7, SDK 34, app 1.7.8-GOOGLE. The main thread is insideChoreographer.doFrame, and the vendor's skipped-frame handler performs a synchronous binder round-trip to the system server to fetch its own system service; the >5 s block is the system server's response latency to that vendor-initiated lookup, which the app cannot act on. The stack has zeroza.kilowatch.ultimatefilemanagerframes, 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. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isBinderProxy.transact/transactNative, containing acom.transsion.hubsdk/com.transsion.hubcoreframe and aServiceManager/ServiceManagerNative/ServiceManagerProxy/IServiceManager$Stub$Proxyservice-lookup frame, with noza.kilowatch.ultimatefilemanagerframes, as a system-side wait 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 notBinderProxy.transact/transactNative— and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside a recursive deep-equals / object-graph comparison while a main-looper Runnable is being dispatched — top frame
kh2.equals(an R8-obfuscatedequalson an app/library model class), underb94.d→uf1.equals→b94.d→iq9.c→jp3.c→aa.runsitting directly onandroid.os.Handler.handleCallback— reported from a Google Google TV Streamer, SDK 34, app 1.7.6-GOOGLE, the same device and session that produced the already-filteredStringBuilder.<init>/appendpost-stall report from the sameaa.runRunnable. The app or a bundled library is comparing two object graphs element-by-element: two non-platformequalsframes with a shared compare helper (b94.d) invoked between them prove a nested value comparison, and every frame strictly above the Runnable'srun()is obfuscated non-platform code with no lock, file I/O, network, or binder frame anywhere on the stack — so the sampled work is pure CPU-bound model equality that cannot by itself hold the main thread for 5 s at realistic data sizes; the >5 s block is device-side CPU starvation (the report'sDlnaFetchThread,DlnaSsdpListenerandDefaultDispatcher-worker-*threads are all RUNNABLE, busy with SSDP/DLNA discovery and content-provider queries, starving the main thread) or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadnow treats a main-thread stack that has a non-platformrun()frame sitting directly onHandler.handleCallback, whose top frame is a non-platformequalsreached through a recursive chain (at least one more non-platformequalsdeeper in the stack), where every frame above therun()is non-platform code and no framework blocking primitive (BinderProxy.transact/transactNative,Object.wait,LockSupport,java.io,libcore.io) appears anywhere, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside blocking work — a lock/wait/park, a binder transact, a file or network I/O frame, a top frame that is not anequalsin a comparison chain, or comparison work reached from app business logic without aHandler.handleCallback-dispatchedrun()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 text-measurement span query while an editable TextView measures itself during a normal frame — top frame
android.text.SpannableStringBuilder.sort(the span-index sort thatgetSpansruns after collecting a line's spans), reached viaSpannableStringBuilder.getSpans-> the emoji-aware spanned wrapper'sgetSpans(an R8-obfuscated bundled-library frame, e.g.androidx.emoji2.text.SpannableBuilder, that delegates span queries to the inner builder) ->SpanSet.init-> theTextLinemeasure chain (handleRun/measureRun/measure/metrics) ->Layout.getLineMax/getLineExtent->TextView.desired/onMeasure, dispatched from a frame-draw measure pass (Choreographer.doFrame/ViewRootImpl.performMeasure/performTraversals) (reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS — the same device and session that produced the already-filterednDrawTextRun,MeasuredText,SpannableStringBuilder.removeSpan,IdentityHashMap.getandView.invalidatereports). This is the measure-path counterpart of the filtered nDrawTextRun draw path: the framework's own line measurement queries the line's spans viaSpanSet.init, andgetSpanssorts the collected span indices — work bounded by the number of spans the app places on the text (search highlights are scoped to the currently loaded text page; syntax highlighting is capped at the edit-mode size limit), so it cannot by itself occupy the main thread for 5 s; the stack has zeroza.kilowatch.ultimatefilemanagerframes — the only non-platform frame is the bundled-library spanned wrapper'sgetSpans, not app business logic. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isSpannableStringBuilder.sort, with aSpannableStringBuilder.getSpansframe, aSpanSet.initframe, aTextLinemeasure frame, aTextView.onMeasure/TextView.desiredframe, and a frame-draw dispatch (Choreographer.doFrame/ViewRootImpl.performMeasure/performTraversals), and noza.kilowatch.ultimatefilemanagerframes, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic or heavy app span work — an app frame on the stack, or a span query not reached from the framework'sSpanSet.init/TextLine/TextView.onMeasuremeasure path — and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the same framework text-measurement span query, one instruction deeper — top frame
android.text.SpannableStringBuilder.getSpansRec(the bounded recursive span collection thatgetSpansruns before it sorts a line's spans), reached viaSpannableStringBuilder.getSpans-> the emoji-aware spanned wrapper'sgetSpans(an R8-obfuscated bundled-library frame, e.g.androidx.emoji2.text.SpannableBuilder) ->SpanSet.init-> theTextLinemeasure chain (handleRun/measureRun/measure/metrics) ->Layout.getLineMax/getLineExtent->TextView.desired/onMeasure, dispatched from a frame-draw measure pass (Choreographer.doFrame/ViewRootImpl.performMeasure/performTraversals) (reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS — the same device and session that produced the already-filteredSpannableStringBuilder.sort,nDrawTextRun,MeasuredText,SpannableStringBuilder.removeSpan,IdentityHashMap.getandView.invalidatereports). This is the identicalgetSpansmeasure-path query as the already-filteredsort-top shape, just sampled during the collection phase that runs before the sort:getSpansRec's recursion depth is bounded by the fixed number of span buckets and the whole collection is bounded by the queried line's span count (search highlights are scoped to the currently loaded text page; syntax highlighting is capped at the edit-mode size limit), so it cannot by itself occupy the main thread for 5 s; the >5 s block is device-side slowness / CPU starvation or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadmeasure-path span-query filter now treats a main-thread stack whose top frame isSpannableStringBuilder.getSpansRec/getSpans— in addition to the existingSpannableStringBuilder.sort— with aSpannableStringBuilder.getSpansframe, aSpanSet.initframe, aTextLinemeasure frame, aTextView.onMeasure/TextView.desiredframe, and a frame-draw dispatch, and noza.kilowatch.ultimatefilemanagerframes, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic or heavy app span work — an app frame on the stack, or a span query not reached from the framework'sSpanSet.init/TextLine/TextView.onMeasuremeasure path — and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the
Threadconstructor while a bundled Google Play module — the Firebase Analytics Measurement dynamite module (com.google.android.gms.dynamite_measurementdynamite, whose classes are R8-obfuscated to short names such asm7.*inside the dynamically loaded module) — creates a Thread from a main-looper Runnable — e.g.Handler.handleCallback→m7.lr.run→m7.sh.e/m7.sh.i→m7.sg.<init>→Thread.<init>(constructor chaining) →Thread.getThreadGroup→Thread.getState→Thread.nativeGetStatus(top frame) — reported from an SDMC HAKO Pro, SDK 34, app 1.7.6-GOOGLE. Constructing a Thread is bounded, allocation-only bookkeeping:getThreadGroupresolves the creating thread's group andgetState/nativeGetStatusread the new thread's status field, and no lock, file/network I/O, or binder frame appears anywhere on the stack — so the currently executing frame (Thread.nativeGetStatus) cannot by itself occupy the main thread for 5 s. The stack has zeroza.kilowatch.ultimatefilemanagerframes: the Thread is created by a bundled-library / Google Play module class constructor (the frame directly below the deepestThread.<init>is a non-platform<init>), not by app business logic — so the >5 s block is device-side slowness / CPU starvation or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadnow treats a main-thread stack whose top frame isThread.nativeGetStatus/Thread.getState/Thread.getThreadGroup/Thread.<init>, with aThread.<init>frame whose direct caller is a non-platform<init>constructor, and no app frames, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside blocking work — the top frame is NOT Thread-construction bookkeeping (it is a lock, file/network I/O, or binder frame), or an app frame appears on the stack — and are still reported.