github Kilowatch/ultimate-file-manager-pro v1.8.1

2 hours ago

Added

  • Native AVIF image decoding support (org.aomedia.avif.android:avif 1.3.0) in the built-in image viewer and thumbnail generator for API levels 26–30, with system ImageDecoder hardware 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 (csvphoto.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 $N token 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 .avif image 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), under ComponentActivity.<init>FragmentActivity.<init>AppCompatActivity.<init>LanguageWelcomeActivity.<init>Class.newInstanceAppComponentFactory.instantiateActivity/Instrumentation.newActivityActivityThread.performLaunchActivity — reported from a SEI Robotics Movix Pro, SDK 28, app 1.8.0-GOOGLE. The currently executing frame is getLifecycle(), 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. The AnrWatchdogThread now treats a main-thread stack whose top frame is getLifecycle, with a Class.newInstance frame and a framework Activity-launch frame (AppComponentFactory.instantiateActivity/Instrumentation.newActivity/ActivityThread.performLaunchActivity), where every za.kilowatch.ultimatefilemanager frame 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 not getLifecycle, 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.append one instruction deeper inside the same freshly dispatched main-looper Runnable — top frame StringBuilder.append with a StringBuilder.<init> frame directly below it (the StringBuilder(String) constructor invokes append internally, so the whole append<init> pair is still the freshly entered Runnable's first statement), then a non-platform run() and Handler.handleCallback beneath — reported from a Google Pixel 6a, SDK 37, app 1.7.6. This is the same post-stall sampling artifact as the previously-filtered StringBuilder.<init>-top and direct StringBuilder.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. The AnrWatchdogThread now treats a main-thread stack whose top frames are StringBuilder.appendStringBuilder.<init> → non-platform run()Handler.handleCallback — in addition to the existing shapes where a single StringBuilder.<init>/append frame sits directly above the run() — 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>/append directly under a Runnable just entered via Handler.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) called UfmFtpServer.stop() synchronously; Apache FtpServer's DefaultFtpServer.stop()NioListener.stop() → Apache Mina AbstractIoAcceptor.unbind() waits on DefaultIoFuture.await0 (an Object.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-cancelled Dispatchers.IO scope kept separate from serviceJob), so onStartCommand/onTaskRemoved/onDestroy never block the main thread; the DLNA/renderer stops were moved onto the same scope and the now-redundant stop wrappers were removed so a cancelled serviceJob can 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 onCreate runs during a framework-driven cold-start Activity launch — e.g. SafPickerActivity.onCreatesetupViews()<obfuscated helper>.findViewById (top frame), under Activity.performCreateInstrumentation.callActivityOnCreateActivityThread.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 own onCreate lifecycle callback the framework invoked — and the currently executing frame is findViewById, 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. The AnrWatchdogThread now treats a main-thread stack whose top frame is findViewById, with exactly one app frame that is an Activity's own onCreate and 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 not findViewById, more than one app frame, or the Activity's onCreate itself 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.onCreateActivity.startActivitystartActivityForResultInstrumentation.execStartActivityIActivityTaskManager$Stub$Proxy.startActivityBinderProxy.transacttransactNative (top frame) — reported from a Xiaomi MiTV-AFMU0, SDK 34, app 1.8.0-GOOGLE. The app merely invoked the one-line framework API startActivity(); 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 own onCreate call-path frame (the onCreate decided to launch the next screen), the wait is still system-side, the same class as the existing unbindService binder filter. The AnrWatchdogThread now treats a main-thread stack whose top frame is BinderProxy.transact/transactNative with an IActivityTaskManager$Stub$Proxy.startActivity frame 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 not BinderProxy.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 calcMax max-walk of the same framework SpannableStringBuilder span-removal bookkeeping — top frame android.text.SpannableStringBuilder.calcMax (a recursion restoreInvariants runs to re-establish the span-order invariant after removing a span, reached via SpannableStringBuilder.removeSpan) — while a main-looper Runnable is being dispatched, with a non-platform run() frame sitting directly on Handler.handleCallback (reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filtered SpannableStringBuilder.removeSpan/restoreInvariants, IdentityHashMap.get, View.invalidate, MeasuredText, and nDrawTextRun reports). This is the identical span-removal chain as the previously-filtered removeSpan-top and IdentityHashMap.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. The AnrWatchdogThread span-removal filter now also treats a main-thread stack whose top frame is SpannableStringBuilder.calcMax, with a SpannableStringBuilder.restoreInvariants frame and a SpannableStringBuilder.removeSpan frame, dispatched from a main-looper Runnable (Handler.handleCallback directly below a non-platform run() 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 a Handler.handleCallback message-dispatch frame on the stack (the app calls setSpan/removeSpan directly, 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-obfuscated run() method) sitting directly on android.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-filtered MeasuredText, nDrawTextRun, SpannableStringBuilder.removeSpan and View.invalidate reports. The sampled Runnable was just entered — its run() is the TOP frame with Handler.handleCallback directly 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 the StringBuilder.<init>/append post-stall artifacts, just sampled one frame earlier at the Runnable's own entry. The AnrWatchdogThread now treats a main-thread stack whose top frame is a non-platform run() directly under Handler.handleCallback (with no Handler.postDelayed frame) 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 bare run() entry directly on Handler.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 SpannableStringBuilder span-removal bookkeeping — top frame java.util.IdentityHashMap.get (the insertion-order-map lookup/update inside restoreInvariants' bounded span-order walk, reached via SpannableStringBuilder.removeSpan) — while a main-looper Runnable is being dispatched, with a non-platform run() frame sitting directly on Handler.handleCallback (reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filtered SpannableStringBuilder.removeSpan/restoreInvariants, MeasuredText, nDrawTextRun, and View.invalidate reports). This is the identical span-removal chain as the previously-filtered removeSpan-top shape, sampled one frame further — restoreInvariants re-establishes the sorted-order invariant by walking the builder's span array and doing an O(1) IdentityHashMap lookup/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. The AnrWatchdogThread span-removal filter now also treats a main-thread stack whose top frame is IdentityHashMap.get/put, with a SpannableStringBuilder.restoreInvariants frame and a SpannableStringBuilder.removeSpan frame, dispatched from a main-looper Runnable (Handler.handleCallback directly below a non-platform run() 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 a Handler.handleCallback message-dispatch frame on the stack (the app calls setSpan/removeSpan directly, 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.onCreateConnectivityManager.registerDefaultNetworkCallback()IConnectivityManager$Stub$Proxy.requestNetworkBinderProxy.transacttransactNative (top frame). The app registered its Wi-Fi transition listener — the NetworkCallback that purges pooled SMB sessions when the device switches networks — synchronously at the end of Application.onCreate(). registerDefaultNetworkCallback is a blocking binder round-trip to the system server's IConnectivityManager, 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). NetworkCallback callbacks 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 during onCreate, 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.invalidate while a TextView invalidates itself after a framework span-removal — top frame View.invalidate, under TextView.spanChangeTextView$ChangeWatcher.onSpanRemovedSpannableStringBuilder.sendSpanRemoved/removeSpan/restoreInvariants, reached from the same main-looper Runnable dispatch (a non-platform run() frame sitting directly on Handler.handleCallback) — reported from a TECNO TECNO KJ5, SDK 33, app 1.7.8-FOSS, the same device and session that produced the already-filtered MeasuredText, nDrawTextRun, and SpannableStringBuilder.removeSpan reports. 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.invalidate is 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. The AnrWatchdogThread span-removal filter now treats a main-thread stack whose top frame is View.invalidate, with a TextView.spanChange frame, a TextView$ChangeWatcher.onSpanRemoved frame, and a SpannableStringBuilder sendSpanRemoved/removeSpan/restoreInvariants frame, dispatched from a main-looper Runnable (Handler.handleCallback directly below a non-platform run() 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 a Handler.handleCallback message-dispatch frame on the stack (the app calls setSpan/removeSpan directly, 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, under MeasuredParagraph.buildForStaticLayoutStaticLayout.generateDynamicLayout.reflow/DynamicLayout$ChangeWatcher.reflow, reached from the IME text-input path (BaseInputConnection.replaceText → the editable's replaceSpannableStringBuilder.replacesendTextChanged → 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-filtered nDrawTextRun and SpannableStringBuilder.removeSpan reports. 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 TextWatcher onTextChanged callbacks 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. The AnrWatchdogThread now treats a main-thread stack whose top frame is MeasuredText$Builder.nBuildMeasuredText/build, with a DynamicLayout.reflow/DynamicLayout$ChangeWatcher.reflow frame and a BaseInputConnection.replaceText frame, 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 (no BaseInputConnection.replaceText frame, e.g. the app calls setText/append directly) — 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-filtered StringBuilder.<init> — directly under an obfuscated app/library run() dispatched by Handler.handleCallback (reported from an Innopia MundoGoTV, SDK 34, app 1.7.7). A single append of 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, with Handler.handleCallback one 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. The AnrWatchdogThread now treats a main-thread stack whose top frame is StringBuilder.append — in addition to the existing StringBuilder.<init> — whose second frame is a non-platform run(), and whose third frame is Handler.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>/append directly under a Runnable just entered via Handler.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 frame androidx.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-fixed SystemJobService.<clinit> shape — ActivityThread.handleCreateServiceAppComponentFactory.instantiateServiceClass.newInstance — just sampled one frame further into the same one-time class-loading/construction cost on a slow or busy device: the stack has zero za.kilowatch.ultimatefilemanager frames, so the app cannot act on it. The AnrWatchdogThread now treats a main-thread stack whose top frame is a bundled-library <init> — in addition to the existing <clinit> — during framework service instantiation (a Class.newInstance frame plus an AppComponentFactory.instantiateService/ActivityThread.handleCreateService frame, 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.moveFile read the entire file into a ByteArray before writing it to the destination (File.readBytes() for local sources, a ByteArrayOutputStream for 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 a lifecycleScope.launch (Main.immediate) around engine.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 with writeStream(path, input, size), moveFile opens the source as an InputStream (a FileInputStream for local sources, the share client's input stream for network sources), and the destination is written via the share client's streaming uploadStream (FTP/OneDrive/TV/Google Drive/Dropbox/WebDAV/S3) or a chunked copyTo output 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 SpannableStringBuilder span bookkeeping operation — top frame android.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-platform run() frame sitting directly on Handler.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. The AnrWatchdogThread now treats a main-thread stack whose top frame is SpannableStringBuilder.removeSpan/restoreInvariants, dispatched from a main-looper Runnable (Handler.handleCallback directly below a non-platform run() 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 a Handler.handleCallback message-dispatch frame on the stack (the app calls setSpan/removeSpan directly, 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, under android.text.Layout.drawTextEditor.drawHardwareAcceleratedInnerEditor.onDrawTextView.onDraw, dispatched from Choreographer.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), but TextView.onDraw only 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 zero za.kilowatch.ultimatefilemanager frames — the only non-platform frame is the AndroidX ConstraintLayout.dispatchDraw in 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, leaving tickerJustRan false). The AnrWatchdogThread now treats a main-thread stack whose top frame is BaseRecordingCanvas.nDrawTextRun/drawTextRun, with a TextView.onDraw frame, an Editor frame (onDraw/drawHardwareAccelerated/drawHardwareAcceleratedInner), a Layout.drawText frame, a frame-draw dispatch frame (Choreographer.doFrame/ViewRootImpl.performDraw), and no za.kilowatch.ultimatefilemanager frames, 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 own onDraw performs 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 fragment arguments (putParcelableArray("items", ...)); fragment arguments are re-serialized into the host Activity's saved-instance-state parcel on every onSaveInstanceState, 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 at android.app.ActivityClient.activityStopped. The items now travel through an in-memory BatchRenameItemsCache (the same pattern already used for media playlists) and only a small cache-key string goes into fragment arguments; the dialog peeks the list back in onCreate and 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 SystemJobService while the system's JobScheduler starts a scheduled job — top frame rr9.hashCode() (the R8-obfuscated WorkManager-internal type used as the active-jobs map key), under HashMap.hash/HashMap.put, under androidx.work.impl.background.systemjob.SystemJobService.onStartJob, dispatched by JobServiceEngine$JobHandler.handleMessage (reported from a Google Pixel 6a, SDK 37, app 1.7.6). JobScheduler delivers job callbacks on the main thread, and onStartJob inserts 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's WM.task-1 thread was RUNNABLE, busy in a background WorkManager task) or a post-stall sample. The stack has zero za.kilowatch.ultimatefilemanager frames — 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 inside onStartJob. The AnrWatchdogThread now treats a main-thread stack that contains a SystemJobService.onStartJob frame, a JobServiceEngine$JobHandler.handleMessage frame, and no za.kilowatch.ultimatefilemanager frames, whose top frame is a hashCode()/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.doFramecom.transsion.hubcore.view.TranChoreographerImpl.skippedFrames (TECNO's ROM-installed Choreographer hook) → com.transsion.hubsdk.trancare.trancareassist.TranTrancareAssistManager.getServiceTranServiceManager.getServiceIBinderServiceManager.getServiceIServiceManager$Stub$Proxy.checkServiceBinderProxy.transacttransactNative (top frame) — reported from a TECNO TECNO KL7, SDK 34, app 1.7.8-GOOGLE. The main thread is inside Choreographer.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 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 BinderProxy.transact/transactNative, containing a com.transsion.hubsdk/com.transsion.hubcore frame and a ServiceManager/ServiceManagerNative/ServiceManagerProxy/IServiceManager$Stub$Proxy service-lookup frame, with no za.kilowatch.ultimatefilemanager frames, 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 not BinderProxy.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-obfuscated equals on an app/library model class), under b94.duf1.equalsb94.diq9.cjp3.caa.run sitting directly on android.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-filtered StringBuilder.<init>/append post-stall report from the same aa.run Runnable. The app or a bundled library is comparing two object graphs element-by-element: two non-platform equals frames with a shared compare helper (b94.d) invoked between them prove a nested value comparison, and every frame strictly above the Runnable's run() 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's DlnaFetchThread, DlnaSsdpListener and DefaultDispatcher-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. The AnrWatchdogThread now treats a main-thread stack that has a non-platform run() frame sitting directly on Handler.handleCallback, whose top frame is a non-platform equals reached through a recursive chain (at least one more non-platform equals deeper in the stack), where every frame above the run() 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 an equals in a comparison chain, or comparison work reached from app business logic without a Handler.handleCallback-dispatched run() 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 that getSpans runs after collecting a line's spans), reached via SpannableStringBuilder.getSpans -> the emoji-aware spanned wrapper's getSpans (an R8-obfuscated bundled-library frame, e.g. androidx.emoji2.text.SpannableBuilder, that delegates span queries to the inner builder) -> SpanSet.init -> the TextLine measure 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-filtered nDrawTextRun, MeasuredText, SpannableStringBuilder.removeSpan, IdentityHashMap.get and View.invalidate reports). This is the measure-path counterpart of the filtered nDrawTextRun draw path: the framework's own line measurement queries the line's spans via SpanSet.init, and getSpans sorts 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 zero za.kilowatch.ultimatefilemanager frames — the only non-platform frame is the bundled-library spanned wrapper's getSpans, not app business logic. The AnrWatchdogThread now treats a main-thread stack whose top frame is SpannableStringBuilder.sort, with a SpannableStringBuilder.getSpans frame, a SpanSet.init frame, a TextLine measure frame, a TextView.onMeasure/TextView.desired frame, and a frame-draw dispatch (Choreographer.doFrame/ViewRootImpl.performMeasure/performTraversals), and 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 or heavy app span work — an app frame on the stack, or a span query not reached from the framework's SpanSet.init/TextLine/TextView.onMeasure measure 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 that getSpans runs before it sorts a line's spans), reached via SpannableStringBuilder.getSpans -> the emoji-aware spanned wrapper's getSpans (an R8-obfuscated bundled-library frame, e.g. androidx.emoji2.text.SpannableBuilder) -> SpanSet.init -> the TextLine measure 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-filtered SpannableStringBuilder.sort, nDrawTextRun, MeasuredText, SpannableStringBuilder.removeSpan, IdentityHashMap.get and View.invalidate reports). This is the identical getSpans measure-path query as the already-filtered sort-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. The AnrWatchdogThread measure-path span-query filter now treats a main-thread stack whose top frame is SpannableStringBuilder.getSpansRec/getSpans — in addition to the existing SpannableStringBuilder.sort — with a SpannableStringBuilder.getSpans frame, a SpanSet.init frame, a TextLine measure frame, a TextView.onMeasure/TextView.desired frame, and a frame-draw dispatch, and 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 or heavy app span work — an app frame on the stack, or a span query not reached from the framework's SpanSet.init/TextLine/TextView.onMeasure measure path — and are still reported.
  • Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the Thread constructor 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 as m7.* inside the dynamically loaded module) — creates a Thread from a main-looper Runnable — e.g. Handler.handleCallbackm7.lr.runm7.sh.e/m7.sh.im7.sg.<init>Thread.<init> (constructor chaining) → Thread.getThreadGroupThread.getStateThread.nativeGetStatus (top frame) — reported from an SDMC HAKO Pro, SDK 34, app 1.7.6-GOOGLE. Constructing a Thread is bounded, allocation-only bookkeeping: getThreadGroup resolves the creating thread's group and getState/nativeGetStatus read 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 zero za.kilowatch.ultimatefilemanager frames: the Thread is created by a bundled-library / Google Play module class constructor (the frame directly below the deepest Thread.<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. The AnrWatchdogThread now treats a main-thread stack whose top frame is Thread.nativeGetStatus/Thread.getState/Thread.getThreadGroup/Thread.<init>, with a Thread.<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.

Don't miss a new ultimate-file-manager-pro release

NewReleases is sending notifications on new releases.