You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added total folder size display (including subfolders, excluding hidden files) for indexed storage drives on both Mobile and TV.
Material You support — a new toggle in the Appearance screen personalises the app with your wallpaper's colours (Android 12+, mobile). When off, the app keeps its original blue colour scheme.
Adaptive file/folder icon tinting that follows the active palette.
The Help & Support form now remembers your email address. A "Remember my email address" checkbox below the email field pre-fills your last used email on future messages — on both Mobile and TV. The email is saved only after a message is sent successfully and is never included in config backups.
Changed
Upgraded Material Components to 1.14.0 and adopted Material 3 Expressive on mobile — modern component shapes, emphasised typography, adaptive colour roles.
Replaced hardcoded colours with Material 3 role tokens so every mobile screen adapts to the active theme.
TV is unaffected: fixed brand palette, pre-existing visuals preserved.
Fixed
Fixed the text editor and Notepad hiding the active line behind the soft keyboard when editing long files. The editor now shrinks to stay above the keyboard with a small gap, keeps the cursor line visible as you type, and dismisses the keyboard when leaving edit mode — on Mobile and TV.
Fixed a false-positive ANR (App Freeze) report when the main thread is blocked resolving the property getter of a MaterialButton's default state-list-animator via reflection while the button is attached to a window — e.g. MaterialButton.refreshDrawableState → drawableStateChanged → StateListAnimator.setState → ObjectAnimator.initAnimation → PropertyValuesHolder.getPropertyFunction → Class.getMethod → getPublicMethodRecursive → getDeclaredMethodInternal — on low-end Android TV devices (e.g. Xiaomi MIBOX4, SDK 31). The default button elevation animation resolves the translationZ getter the first time, forcing the framework to walk and verify the whole TextView class hierarchy; on slow or busy devices that one-time reflection cost exceeds the 5 s watchdog threshold. The blocking work is entirely framework reflection — the only non-platform frame is the view's own drawableStateChanged lifecycle callback that the framework invokes to start its own default animation, not app business logic — so the AnrWatchdogThread now treats a stack whose top frame is Class.getMethod/getPublicMethodRecursive/getDeclaredMethodInternal under PropertyValuesHolder.getPropertyFunction + ObjectAnimator.initAnimation + StateListAnimator.setState/start, with no za.kilowatch.ultimatefilemanager frames, as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep an app frame on the stack (or reach the reflection without a StateListAnimator frame) and are still reported.
Fixed an ANR (App Freeze) when opening or editing large text files on low-end Android TV boxes (e.g. ZTE OTT Xview+ AV1, SDK 30). The text viewer's content EditText uses wrap_content width inside a horizontal-scroll layout, so every setText + layout pass makes TextView.onMeasure walk every glyph of the loaded text on the main thread (Layout.getDesiredWidthWithLimit → TextLine.metrics → Paint.getRunAdvance) — up to 64 KB per page in view mode and up to the whole document (~1 MB) in edit mode, exceeding the 5 s watchdog threshold. PAGE_BYTE_SIZE is now 16 KB (4× less glyph measurement per layout pass) and edit mode is capped at 128 KB: documents larger than that stay viewable via pagination but show a "File too large to edit" message instead of loading the whole file into the editor and freezing the app.
Fixed a false-positive ANR (App Freeze) report when the main thread is blocked laying out RecyclerView rows while handling a TV D-pad focus-navigation key event on low-end Android TV devices (e.g. onn 4K Streaming Box, SDK 34). When focus search fails inside the visible rows, LinearLayoutManager.onFocusSearchFailed fills the list in the search direction to find the next focusable row, and every row it attaches runs the framework's window-attach + drawable-state refresh on the main thread (addView → dispatchAttachedToWindow → refreshDrawableState → AppCompatCheckBox.drawableStateChanged); on a slow or busy box that synchronous layout of many rows exceeds the 5 s watchdog threshold while the user simply presses a D-pad arrow. The stack has zero UFM frames — the only non-platform frame is the checkbox's own drawableStateChanged lifecycle callback that the framework invokes during attach, and the rest is AndroidX RecyclerView focus-search layout machinery plus framework view attach, not app business logic — so the AnrWatchdogThread now treats a stack whose top frame is drawableStateChanged/refreshDrawableState, with RecyclerView.focusSearch, a LinearLayoutManager frame and a View/ViewGroup.dispatchAttachedToWindow frame, and no za.kilowatch.ultimatefilemanager frames, as a library-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep an app frame on the stack (or are caught inside app bind code whose top frame is not a drawable-state callback) 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 while unbinding a service connection — e.g. Handler.dispatchMessage → app Handler.handleMessage → ContextWrapper.unbindService → ContextImpl.unbindService → (a device-injected system-service hook proxy, e.g. com.vlite.sdk, which wraps the call in a dynamic Proxy) → IActivityManager$Stub$Proxy.unbindService → BinderProxy.transact → transactNative (reported from a Xiaomi Redmi K20 Pro, SDK 29, app 1.7.7). The app merely invoked the one-line framework API; the >5 s block is the system server's response latency to the service-connection teardown, which the app cannot act on. The AnrWatchdogThread now treats a stack whose top frame is BinderProxy.transact/transactNative with an IActivityManager$Stub$Proxy.unbindService or ContextImpl.unbindService frame as a system-side wait — even when app call-path frames (the Handler message that decided to unbind) or a device hook's proxy frames are present — 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) and are still reported.
Fixed a false-positive ANR (App Freeze) report when the main thread is blocked inside the AndroidX Activity lifecycle dispatch while an Activity is starting — e.g. StorageBrowserActivity.onStart → AppCompatActivity.onStart → FragmentActivity.onStart → (FragmentManager / LifecycleRegistry ON_START / AppCompatDelegate applyDayNight dispatch) — reported from a Samsung Galaxy S25 Ultra (SM-S948U1), SDK 36, app 1.7.7. The app's own onStart is a framework-invoked lifecycle callback that contains no business logic (in this app it just calls super.onStart() and registers a broadcast receiver); the actual block is entirely inside the bundled library's lifecycle machinery (activity super-chain dispatch, fragment state moves, lifecycle-event dispatch), which the app cannot act on — the same class of system-side wait as the pure-framework filter, except the stack legitimately carries the activity's own onStart frame. The AnrWatchdogThread now treats a main-thread stack whose only app frame is an Activity's own onStart lifecycle callback, whose currently executing top frame is a bundled-library (obfuscated) frame, and which has a library onStart frame sitting between the activity's onStart and the blocking top frame (proving the block is inside the super-chain, not app code running after super.onStart() returned) as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep app business frames on the stack — either more than one app frame, or the activity's onStart directly calling into the blocking code with no intermediate library onStart frame — and are still reported.
Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at the very first instruction of a freshly dispatched main-looper Runnable — top frame java.lang.StringBuilder.<init> (the StringBuilder constructor, a single-instruction allocation that cannot occupy the thread for 5 s), under an obfuscated app/library run() method dispatched directly by Handler.handleCallback (reported from a Google TV Streamer, SDK 34, app 1.7.6). The Runnable had just been entered and executed its first statement, so the >5 s block cannot have happened inside it; the block occurred in a PREVIOUS main-looper message and the 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.<init>, whose second frame is a non-platform run(), and whose third frame is Handler.handleCallback — proving the Runnable was just dispatched by the main Handler — 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 constructor 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 during a cold-start layout inflation of an Activity layout — top frame TextView.setCompoundDrawablePadding (a trivial compound-drawable padding setter that only assigns four int fields and cannot occupy the thread for 5 s), inside the MaterialButton constructor, under the framework LayoutInflater inflating the first Activity's XML while its onCreate runs setContentView (reported from a SPIDER RED 10, SDK 29, app 1.7.7, on the LanguageWelcomeActivity welcome screen). On a slow or busy device the one-time cost of cold-starting the first Activity — class loading, resource decoding and the MaterialButton constructor — can exceed the 5 s watchdog threshold, and the sampled frame is a single-instruction setter inside that framework/library inflation, which the app cannot act on. The AnrWatchdogThread now treats a stack whose top frame is TextView.setCompoundDrawablePadding with a MaterialButton.<init> frame and a LayoutInflater frame, and whose app frames — if any — are all Activity lifecycle classes, as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep an app frame that is not an Activity class (e.g. adapter bind code) or a top frame that is not this setter under a MaterialButton constructor + LayoutInflater, and are still reported.
Fixed an ANR (App Freeze) when the main thread is blocked in QueuedWork.waitToFinish() while an Activity stops, waiting for a queued SharedPreferencesapply() write to fsync on slow low-end storage (reported from an SCBC R4, SDK 30, app 1.7.7). The file-tag map (ufm_file_tags, one key per tagged file — unbounded, rewritten in full on every change) and the media player's resume-state blob (ufm_player_state, the entire serialized playback queue — up to thousands of items) were written with apply(); the framework then blocks the main thread on QueuedWork.waitToFinish() at Activity.onStop() until that fsync finishes, which exceeds the 5 s watchdog threshold when the prefs file is large and the device storage is slow. Both stores now persist via commit() on a dedicated single-thread background writer so they never enter QueuedWork, and the main thread is never blocked at lifecycle boundaries. File-tag writes are additionally batched — the multi-file tag dialog and global tag deletion rewrite the tag map in a single background commit() instead of one apply() per file, move/copy tag-path updates use the same background commit(), and an in-memory mirror of the tag map (invalidated after a settings restore) preserves immediate read-after-write consistency. Resume-state writes (saveState/clearState) likewise move off the main thread.
Fixed a false-positive ANR (App Freeze) report when the main thread is blocked on a synchronous IPC call to the system's autofill service while a view enters the window — e.g. View.layout → View.notifyEnterOrExitForAutoFillIfNeeded → AutofillManager.notifyViewEntered → notifyViewEnteredLocked → tryAddServiceClientIfNeededLocked → SyncResultReceiver.getIntResult → SyncResultReceiver.waitResult → CountDownLatch.await — on Android TV devices (e.g. TCL Smart TV, SDK 34, app 1.7.7). When a view (e.g. inside a dialog) is laid out, the framework synchronously asks the system autofill service whether it should be autofilled; on a slow or busy TV that binder round-trip to the system autofill service exceeds the 5 s watchdog threshold. The stack has zero UFM frames — the only non-platform frames are bundled-library (AndroidX) view-layout frames such as AlertDialogLayout.onLayout, which break the pure-framework filter — so the wait is entirely system-side and the app cannot act on it. The AnrWatchdogThread now treats a main-thread stack that contains a SyncResultReceiverwaitResult/getIntResult frame and an AutofillManagernotifyViewEntered/notifyViewEnteredLocked/tryAddServiceClientIfNeededLocked frame, with no za.kilowatch.ultimatefilemanager frames, 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 crash (android.content.ActivityNotFoundException) when opening the TV Remote screen from the main menu on TV builds — reported from a "Welcome S25 Ultra" device, SDK 31, app 1.7.8-FOSS. TvRemoteActivity and TvSetupGuideActivity were declared only in the mobile source-set manifest, so every tv* variant (FOSS/Google/Amazon) compiled the classes but had no <activity> entry for them; tapping the TV Remote tile (shown when DeviceUtils.isTvDevice() returns false, e.g. on Android boxes that report UI mode as NORMAL) called startActivity(Intent(..., TvRemoteActivity::class.java)) and threw "Unable to find explicit activity class". Both activities are now declared in the shared main manifest so they resolve on every variant; the duplicate declarations were removed from the mobile manifest.
Fixed an ANR (App Freeze) when the system delivers TRIM_MEMORY_COMPLETE to UfmApplication.onTrimMemory — reported from a Xiaomi MIBOX4, SDK 28, app 1.7.8-GOOGLE. The framework invokes onTrimMemory on the main thread (via ActivityThread.handleTrimMemory), and the TRIM_MEMORY_COMPLETE branch synchronously ran SmbSessionPool.closeAll() and NetworkHttpProxyServer.stop(). Closing pooled SMB sessions performs blocking network I/O (each session.close() can wait up to the SMB socket timeout for its LOGOFF/connection-close round-trip), and stopping the HTTP proxy closes the server socket and every streaming handle under each session's readLock — together exceeding the 5 s watchdog threshold on low-end boxes. The teardown is now offloaded to a named background daemon thread (ufm-memory-trim); onTrimMemory returns immediately, so the main thread never blocks on SMB session or proxy shutdown. The cleanup stays best-effort (the SMB server has its own idle timeout), so the main-thread freeze is gone without losing the courtesy teardown when the process is actually killed.
Fixed an ANR (App Freeze) when leaving the PDF viewer while a page was still rendering — reported from a Sercomm XstreamIPTV2-SM, SDK 34, app 1.7.8-GOOGLE. PdfViewerActivity.onDestroy closed the renderer via runBlocking on the main thread while a page render coroutine held the render mutex for the whole blocking native page.render() call; on a slow device that render can exceed 5 s, parking the main looper in LockSupport.parkNanos waiting for the mutex. onDestroy now sets the renderer-closed flag and cancels the render scope immediately, then closes the PdfRenderer and file descriptor on a dedicated daemon thread (ufm-pdf-close) that acquires the mutex as soon as the in-flight render finishes — the main thread no longer waits on the render, so backing out of a PDF mid-load no longer freezes. The synchronous close path used when re-opening a password-protected PDF is unchanged and stays safe (no render is in flight while the password dialog is showing).
Fixed a false-positive ANR (App Freeze) report when the main thread is blocked applying the theme style to a ProgressBar while a RecyclerView row is inflated during a TV D-pad focus-navigation fill — e.g. ViewRootImpl$ViewPostImeInputStage.performFocusNavigation → View.focusSearch → RecyclerView.focusSearch → LinearLayoutManager.onFocusSearchFailed → fill/layoutChunk → adapter onCreateViewHolder → LayoutInflater.inflate → ProgressBar.<init> → Context.obtainStyledAttributes → ResourcesImpl$ThemeImpl.obtainStyledAttributes → AssetManager.applyStyle → nativeApplyStyle — on low-end Android TV devices (e.g. Hisense SmartTV 4K FFM, SDK 31). When focus search fails inside the visible rows, the layout manager fills the list in the search direction and every new row it inflates runs the framework's synchronous style-application on the main thread; on a slow or busy box that inflation + theme-attribute application exceeds the 5 s watchdog threshold while the user simply presses a D-pad arrow. The blocking work is entirely inside the framework's AssetManager.nativeApplyStyle during view construction — the app's only contribution is its adapter inflating its own row layout (the RecyclerView.focusSearch frame proves it is the focus-navigation fill path, not a normal scroll) — so the AnrWatchdogThread now treats a stack whose top frame is AssetManager.nativeApplyStyle/applyStyle, with obtainStyledAttributes, View.<init>, LayoutInflater, RecyclerView.focusSearch and LinearLayoutManager frames, as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app code (the top frame is not nativeApplyStyle, or there is no focus-search fill path) and are still reported.
Fixed a false-positive ANR (App Freeze) report when the main thread is blocked reading a vector drawable's string-pool data from the APK while a MaterialCheckBox constructor loads its animated check drawable during a layout inflation — e.g. LayoutInflater → com.google.android.material.checkbox.MaterialCheckBox.<init> → Resources.getDrawable → AnimatedVectorDrawable.inflate → VectorDrawable.inflate → VectorDrawable$VFullPath.updateStateFromTypedArray → TypedArray.getString → AssetManager.getPooledStringForCookie → ApkAssets.getStringFromPool → StringBlock.getSequence → StringBlock.nativeGetString (top frame) — on low-end Android TV devices (e.g. ZTE Claro TV Box 4k, SDK 34, app 1.7.8). This is a framework resource decode / cold resource-cache cost during view construction, not app business logic: the stack has zero UFM frames and the only non-platform frames are the Material view constructor and AndroidX layout/fragment machinery, so the app cannot act on it. The AnrWatchdogThread now treats a main-thread stack whose top frame is StringBlock.nativeGetString/getSequence, with a MaterialCheckBox.<init> frame, an AnimatedVectorDrawable.inflate frame, a VectorDrawable inflate frame and a LayoutInflater frame, and 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 the string-pool read under a checkbox constructor + LayoutInflater) and are still reported.
Fixed a false-positive ANR (App Freeze) report when the main thread is blocked building a content:// URI for a share/open action through FileProvider while the device is slow or busy — e.g. the "Standard share" flow (performStandardShare → FileProvider.getUriForFile → Uri.encode, top frame) triggered by a TV D-pad OK key event — reported from a ZTE Claro TV Box 4k, SDK 34, app 1.7.8. Building the content URI is a trivially fast framework operation: Uri.encode walks the file path once, and getUriForFile only looks up the cached path strategy, builds a string and parses the resulting content URI, so neither can occupy the main thread for 5 s; even the multi-file ACTION_SEND_MULTIPLE loop is bounded by the ~1 MB binder transaction limit on the EXTRA_STREAM URI list (roughly ten thousand files, tens of milliseconds). The >5 s block is device-side slowness/CPU starvation while the app runs its standard, fast share code, which the app cannot act on. The AnrWatchdogThread now treats a main-thread stack whose top frame is android.net.Uri.encode with an androidx.core.content.FileProvider frame as a system-side wait and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside heavy app business logic (the currently executing frame is not Uri.encode under a FileProvider call) and are still reported.