Repository navigation
ADB Application Manager Pro v7.12.10
A patch release: the app now asks before it installs a downloaded app in adb, Shizuku or root mode, twenty-one fixes from read-only audits of the archive code, the Morphe Patcher (a question before a custom patch bundle is loaded, the signing key shared through the share sheet) and the font setting, real app icons in the app menus, a "File not found" label in Patched APKs, and a Refresh button for the app list. Each is tested on a computer.
- Installs of downloaded apps in adb, Shizuku and root mode ask first (#109, C-011). In those modes a store install used to run with no question, taking the address, package and checksum from the page; a script in the page could install any
httpsAPK as a new app. A dialog of the app itself (the page cannot press it) now asks before the install. It lists what the app found out for itself first: the host the file finally came from after redirects (a name with non-ASCII letters is shown in itsxn--form), whether the app is new or replaces the installed one, and whether the file matched the checksum that came with the install request. Below it, labelled "not checked" and always in quotation marks, are the package and version written in the file and the name the page gave. No answer in two minutes, or closing the app window, counts as No (pressing Home leaves the dialog open). Standard mode is unchanged (the system installer already asks). The dialog is not a boundary against a page that already has a shell in the active mode (such a page can tap Install itself); the decision is recorded indocs/COPILOT_CLAUDE_HANDOFF.md(C-011). Not run on a device. - Archives: an entry is capped by the free space (#121, audit Z-1). Extracting a zip, tar, 7z or RAR archive could write far more than the archive's file size suggests (a 10 KB sparse tar that declares 6 GiB, a small 7z of zeros) and fill the phone's storage. Each entry may now write only what is free less a 64 MB reserve, and one that declares more is refused in words before anything is written. Tested on a computer; not run on a device.
- Archives: tar hard links (#122, audit Z-2). A hard link in a tar was extracted as an empty file and counted as done. It is now a copy of the file it shares, or skipped with a note when that file is not part of the extraction. Tested on a computer; not run on a device.
- Morphe Patcher: a job id that names a folder (#119, audit M-8). A patch started with the job id
..emptied the whole Morphe folder (sources, signing key, patched APKs). Job ids are now 1 to 40 letters, digits, dashes and underscores. Tested on a computer; not run on a device. - Morphe Patcher: importing a signing key (#120, audit M-5). Importing a text file, or a keystore with the wrong password, replaced the signing key and the failure only showed at the next patch. The file is now opened with the password and must hold a key named Morphe first; the old key is kept as a backup file. Tested on a computer; not run on a device.
- Morphe Patcher: one patch at a time, really (#123, audit M-7). The check for a patch already running read a name and then wrote it, so two patch calls arriving together (a double tap, or a script in the page) could both be accepted. Taking the one run slot is now a single atomic step. Tested on a computer; not run on a device.
- Morphe Patcher: a finished patch is not lost when Downloads cannot be written (#124, audit M-3). When the copy into
Downloads/Morphe Patcherfailed, the fallback into the app folder reused the same folder name (the millisecond) and failed too, losing the patched APK and leaving an empty folder. Each filing now gets a free name, and a failed one removes what it wrote and puts the APK back. Tested on a computer; not run on a device. - Morphe Patcher: two source reads at once no longer cut each other's files (#125, audit M-2). Reading the patches of two sources at the same time rewrote the job file and deleted the events file the first read was using, so the first waited its full four minutes. A run now takes the engine before it touches its files, and the second read finds the first one's answer in the cache. Tested on a computer against a fake service; not run on a device.
- Morphe Patcher: Stop before the service starts (#130, audit M-4). Stop pressed before the patcher service had started was lost: the page was told "Cancelled" while the engine, started afterwards, kept patching. A Stop is now remembered, so a run that has not started its engine never starts it, one that arrives while the service starts is passed on, and one for any other job id changes nothing. Tested on a computer against a fake service; not run on a device.
- Morphe Patcher: a finished patch that the app never filed (#129, audit M-9). The patcher runs in a process of its own and can finish after the app was killed; its patched APK then stayed in a work folder for good. When the Patched APKs list opens, such runs are now filed (from the request saved with the run) and the folders of failed or long-dead runs are removed; the run in progress is never touched. Tested on a computer; not run on a device.
- Morphe Patcher: Patched APKs entries are not forgotten (#127, audit M-10). An entry whose APK was kept in Downloads was deleted, with its log, when the file could not be seen for a moment (storage access revoked, the card not mounted). It now stays in the list, marked missing. Tested on a computer; not run on a device.
- Morphe Patcher: a copy is whole or absent (#126, audit M-11). A copy of a patched APK or of the signing key that failed half way left a partial file that looked real and replaced a good file already there. Copies now go through a hidden
.partfile that is renamed when complete. Tested on a computer; not run on a device. - Font setting: a stalled font source no longer freezes it (#128, audit F-1). Picking a font from a source that stops answering ignored the 30 second limit and held a lock, so Apply and Clear waited behind it. The copy now stops at its limit and the lock is taken only to swap files. One change in behaviour: a pick that finishes after a newer pick or a Clear is dropped ("A newer font was chosen.") instead of overwriting it. Tested on a computer; not run on a device.
- Archives: a huge tar header is refused (#131, audit Z-3). A tar whose long-name or extended header declared 1.5 GiB (in a file of 1.5 MB) ran the app out of memory when it was opened or listed. Such a header is now refused in words (over 1 MiB for a name, over 8 MiB for an extended header); real archives need far less. Tested on a computer; not run on a device.
- The app menu shows the app's own icon (#132). The tile left of the app's name in the menu of a single app used to show the first letter of the name. It now shows the app's icon (the one the app list uses, with the icon pack you chose), asks the phone for it once when it is not known yet, and keeps the letter until it arrives, when the phone has none, or when the icon cannot be drawn. An icon that arrives for another app does not replace the tile of the app in the menu, and the tile stays 44 px square under a long name. Tested on a computer (UI script
t155); not run on a device. - Connected Devices: real app icons in the list and in the app menu (#133). The rows of the app list showed an icon only when this phone happened to have it cached, and the app menu of that tab had no tile at all. The list now asks the phone once for the icons it does not have and puts each one on its row when it arrives; the app menu gets the same tile as the single-app menu (the icon, the first letter until it is known, nothing for a menu that is not about an app). The icons come from this phone, so an app that exists only on the other device keeps its letter. Tested on a computer (UI script
t158); not run on a device. - Patched APKs: a "File not found" label (#134). An entry kept in the list since the M-10 fix (its APK in Downloads is out of reach) now says so: a "File not found" chip and one sentence of explanation, with Install, Share and Save to Downloads switched off; Log and Delete stay on. The two new strings are in all 13 translated dictionaries, and the dictionaries drop six strings of the cheat-sheet gist loader that the page no longer has. Tested on a computer (UI script
t156); not run on a device. - Font search: a time limit per file, Stop when Settings is left, no collections in the list (#135, audit F-2, F-3, F-4). The 100 ms scan limit was checked only when a folder was entered, so a folder with 120,000 files ran 1.2 s past it without saying the search had stopped early; the clock is now read every 16 files, and the page's "stopped at its limit" note shows. Leaving Settings during a search only made the page drop the answer while the phone kept walking storage for up to 25 s; the walk now checks for a cancel before every file and the page asks for one when Settings is left (the phone answers "cancelled", the page tidies up without a message; a late cancel never stops a newer search). A font collection saved with the name
.ttfor.otfwas listed but failed when chosen ("A font collection (.ttc) cannot be used here"); a file that starts with thettcftag is now left out of the list like a.ttcfile (choosing such a file by hand still gives the reason). Tested on a computer (UI scriptt157, Java suitefontscan); not run on a device. - Archives: more than 500,000 entries is refused in words, not listed in part (#136, audit Z-4, Z-5). A tar with 2 million empty entries (a 14 MB tar.gz) or a 7z of 1 million empty files (300 KB) ran the app out of memory when it was opened, and an archive over the old limit was listed cut off without saying so, which also made "delete after extract" compare against the cut list. The entry limit for tar and 7z is now 500,000 (the zip limit), the names of the entries may take at most 40 MB, and an archive past a limit is refused with a sentence that says so, with no part of it shown, extracted or counted. The memory limit of the 7z reader is 100 MiB (about 500,000 entries): a 7z whose compression needs more than 100 MiB of memory (7-Zip's highest PPMd level, for one) is now refused in words instead of attempted. Tested on a computer at a 256 MB heap; not run on a device.
- Archives: opening a compressed tar can be cancelled (#138, audit Z-6). Opening a tar.zst, tar.bz2, tar.xz, tar.gz or tar.lz4 unpacks every entry's data just to find the next header (minutes for a big one), and it ran on the one thread that answers the page, so nothing else could be answered, not even a Cancel. It now opens in the background: the File Manager shows "Opening ..." with progress and a Cancel button, and Cancel (or leaving the File Manager, closing the archive view or closing the window) stops the listing within a fraction of a second. A file the app cannot read itself (one staged through the shell, up to 3 GiB) is first copied to the app's folder; that copy runs before the background open and cannot be cancelled. Zip, 7z, RAR, plain tar and single compressed files still answer at once. Previewing one entry of a compressed tar and extracting are not cancellable inside an entry. Tested on a computer; not run on a device.
- Morphe Patcher: the app asks before a custom patch bundle is first loaded (#137, audit M-1). A patch bundle (.mpp) is code, and the patch engine runs it inside this app (all-files access, internet, install packages) as soon as it reads the file; adding a source, adding a local file or tapping Update was enough, with no question. A dialog of the app itself now asks before a custom bundle is first handed to the engine, with Allow / Don't allow: the source, the host the file finally came from, its size, the start of its SHA-256, whether the source's published checksum matched, and whether you approved it before. What the source wrote about itself is shown only in quotes under "not checked". An approval belongs to the file's hash, so an updated or swapped file asks again; the engine reads a private copy of the approved bytes, never the live file. No answer in two minutes is a No. The pre-installed source is exempt, bundles already on disk are approved once at the first start with this version, and a source that is switched off is no longer loaded. The dialog is not a boundary against a page that already has a shell (it could press the button or edit the approved list, as with the install question). Still open: the bundle's
.sigis not checked, and the engine does not run in an isolated process. Tested on a computer (203 checks); not run on a device. - Morphe Patcher: the signing key is shared through the share sheet, not copied to Downloads (#141, audit M-13). "Export the key" used to copy
morphe.keystoretoDownloads/Morphe Patcher/, where it stayed readable by apps with all-files access and by file-sync tools, and whoever holds that key can sign an APK that Android installs as an update of every app patched here. Both Export buttons now ask first ("Share the signing key?") and open the Android share sheet for a private, short-lived copy: it is removed after 10 minutes, at the next export and at the next start of the app, and is served only to the app you pick in the sheet. Old exports already in Downloads stay where they are (delete them yourself). The key's alias and password are still the fixed wordMorphe. Tested on a computer; not run on a device. - Apps: a Refresh button for the app list (#143). The Apps tab had no way to reload the installed apps by hand. A round icon button, the last control of the search bar (after the search options and the clear x), now reloads the list with the same load the app runs after every action, so read-only and not-connected modes behave as before (the same list, the same "No Applications Loaded" message when it fails). While it loads the button is disabled, spins (not when reduced motion is on) and is marked busy for at least 0.45 s; a second tap does nothing until it is done. The search text, sort, filters, selection and how far the list is scrolled are kept. No new text (the name is the existing "Refresh", in all 13 languages). Tested on a computer at 320 and 412 px; not run on a device.
- Not run on a device: none of the above has been run on a phone by the people and tools that wrote it; every item was tested on a computer (Java suites, scripted page tests with a mock of the app, a build that ends signed). No phone check of v7.12.9 came back before this release, so nothing from one is in these notes. Section 20 of
docs/DEVICE-TEST-CHECKLIST.mdlists the phone checks for this release (the install question, the Morphe bundle question, the signing-key share sheet, archive limits and Cancel, icons and labels, the Refresh button) anddocs/RELEASE-CHECKLIST-v7.12.10.mdthe steps after publishing. - Known gaps, left for a later release (limits of this release's own fixes; the complete backlog of open audit findings is items 10 to 12 of
docs/COPILOT_CLAUDE_HANDOFF.md): for archives, previewing one entry of a compressed tar and extracting a single huge entry cannot be cancelled inside the entry, and a shell-staged copy cannot be cancelled (Z-6a to Z-6c, and Z-6d, an open question about a damaged tar.zst falling back to the text viewer); for the Morphe Patcher, the signing key's alias and password are still the fixed wordMorphe(the second half of M-13), a bundle's.sigfile is not checked and the patch engine does not run in an isolated process (M-1), and a page that has a shell can still press the new dialogs or edit what they remember. In adb, Shizuku and root mode a store install is confirmed by the app itself since #109; no other install path was changed.