Summary
- Screen Time keeps its state in two remote-management databases. Common advice treats them as a usage source; on current iPhones the usage tables are usually empty.
- This pull request adds eight iLEAPP artifacts that report what the stores do hold: settings, organization settings, users and devices, blueprints, installed apps, usage, change history and deleted-row entries.
- Counts on three further extractions equal an independent
count(*). It was merged on 25 October 2026. - A row says what the store held. It does not show that a person used the feature, or that a deleted app left the phone.
- 8artifacts added
- +2,577lines added
- 12unit tests
- 26 of 26CI jobs passed
The issue
Advice on the Screen Time database is short: it holds app usage by app and by hour, so take a full file system extraction and parse the usage tables. That advice dates from iOS 12. An examiner who follows it on a current phone opens the store and finds the usage tables empty, and may conclude that the device was not used or that Screen Time was off. Before this contribution iLEAPP had no Screen Time artifact at all, so the store was opened by hand or not at all.
On 17 iPhone stores in the Lab's research corpus, usage rows were present on only 4. Six of the seven iOS 26 stores whose Screen Time flag was on held none. What the stores do hold is configuration (a settings row on every store), an installed-app list on 11, and Core Data persistent history on 12, which keeps delete entries for rows that are no longer in the live tables. Four stores held nothing beyond the single configuration row.
So the question is not only "how much was the phone used". It is also "what was configured, which apps did the store list, and what was deleted", and an empty usage table answers none of those. Figure 1 shows how little of the store the usage chain covers.
Show this figure as a table
| Content | Stores of 17 |
|---|---|
| Settings row | 17 |
| Blueprint row | 16 |
| History transactions | 12 |
| Installed-app list | 11 |
| Installed-app delete entries | 8 |
| Usage rows | 4 |
The essence
The contribution adds eight artifacts that read the two remote-management stores, RMAdminStore-Local.sqlite and RMAdminStore-Cloud.sqlite, from a full file system extraction. They report the store settings, the organization settings, users and devices, blueprints with their declaration payloads decoded, the installed-app list, usage tallies, the Core Data change history, and the deleted-row entries that keep an identifier after the row is gone. The passcode is reported as present or absent and its value is never read.
The work is separate from the sysdiagnose ManagedSettings artifacts. It reads the database on the file system, not a sysdiagnose.
| Artifact | Tables read | Reports |
|---|---|---|
| Settings | ZSCREENTIMESETTINGS | Store-level flags, shown as Yes and No |
| Organization Settings | ZCOREORGANIZATIONSETTINGS | Communication and safety policies; passcode present or absent |
| Users and Devices | ZUSERDEVICESTATE, ZCOREUSER, ZCOREDEVICE | Users, devices and per-device state |
| Blueprints and Configurations | ZBLUEPRINT, ZBLUEPRINTCONFIGURATION | Blueprints with the declaration payload decoded |
| Installed Apps | ZINSTALLEDAPP | The app list the store keeps |
| Usage | ZUSAGEBLOCK and the category, timed and counted item tables | Usage blocks and tallies; unverified on real data |
| Change History | ATRANSACTION, ACHANGE | Persistent-history transactions with author, bundle and change counts |
| Deleted Rows | ACHANGE where ZCHANGETYPE = 2 | Delete entries with the tombstone values as stored |
Our methodology
Core Data names its tables after the model entities, with a Z prefix, and keeps an entity table that maps numbers to names. We read the schema from the stores and wrote each query against it, with the results of three habits visible in the code. A table or column that is absent gives no rows for that artifact and not an error, so older stores still run. Flags are shown as Yes and No, with a blank for NULL and any other number kept as stored. Core Data dates are converted to UTC, and each report puts its time columns first. Binary tombstone values are shown as hexadecimal, and the passcode columns are reduced to 0 or 1 inside the SQL query so that no passcode text leaves it.
The search pattern ends in RMAdminStore-*.sqlite*, so the log and shared-memory files are matched beside the database, and the code opens only the main files. The Lab report behind this work measured why that matters: reading the database without its write-ahead log changed at least one count on 14 of 17 stores.
Validation compared the artifacts with plain SQL. For the review of this pull request, three more iPhone extractions (iOS 26.5.2, 26.6 and 26.6.2) were run through the real tool, and independent count(*) on the store tables, with no iLEAPP code, gave the same numbers as the reports (Figure 3). Earlier runs covered five other extractions. On the 26.6.2 store the four deletes are four ZCHANGETYPE = 2 rows in one transaction. The Lab report records 136 of 136 counts equal to independent SQL (eight artifacts on 17 stores), and that the first run on real stores exposed a schema error: timed usage items reach their block through the category row, not through a block column of their own. The query now follows that path.
The output check flagged a few columns as empty or constant: a communication-safety flag that is NULL in the store on two stores, and, on the 26.6.2 store, a timestamp and transaction row shared by the four deletes. Each is now named in the artifact notes. The fixtures are synthetic: a generator builds stores with invented values in two shapes, a managed child profile with usage rows and the plain unmanaged shape seen on real iOS 26 stores. The pull request adds twelve unit tests and two registered cases per artifact, which pass 16 of 16 once the harness uses an absolute temporary folder, and 26 of 26 CI jobs passed.
Show this figure as a table
| Table read | Artifact |
|---|---|
| ZSCREENTIMESETTINGS | Settings |
| ZCOREORGANIZATIONSETTINGS | Organization Settings |
| ZUSERDEVICESTATE, ZCOREUSER, ZCOREDEVICE | Users and Devices |
| ZBLUEPRINT, ZBLUEPRINTCONFIGURATION | Blueprints and Configurations |
| ZINSTALLEDAPP | Installed Apps |
| ZUSAGEBLOCK and the category, timed and counted item tables | Usage |
| ATRANSACTION, ACHANGE | Change History |
| ACHANGE where ZCHANGETYPE = 2 | Deleted Rows |
Show this figure as a table
| Artifact | 26.5.2 | 26.6 | 26.6.2 |
|---|---|---|---|
| Settings | 1 | 1 | 1 |
| Organization Settings | 1 | 1 | 1 |
| Users and Devices | 1 | 1 | 1 |
| Blueprints and Configurations | 1 | 1 | 1 |
| Installed Apps | 336 | 0 | 0 |
| Usage | 0 | 0 | 0 |
| Change History | 1 | 0 | 4 |
| Deleted Rows | 0 | 0 | 4 |
The value
With these artifacts an examiner can say what the store held when the extraction was taken: whether Screen Time and cloud sync were flagged on, which organization settings and blueprints were present, which apps the store listed, and which identifiers the history shows as deleted. The deleted-row entries are the most useful for a case. On eight stores in the Lab's report, 218 installed-app delete entries cover 207 identifiers, and 173 of them are absent from the live list of the same store (Figure 4).
The limits are firm. A tombstone records a deletion, not that an app left the phone: 34 of the 207 identifiers are in the live list again. An empty usage table supports no statement about use, and the usage artifact is exercised only by a synthetic store because usage tables were empty on all eight real devices checked during this review. The installed-app display name was empty on every row examined in the Lab's parser-development set, so the bundle identifier is the only name. Older iOS releases and iPad were not available for this review and are not verified, and the notes say how each artifact reads when a row is absent. Every reading should state whether the log was applied.
Show this figure as a table
| Group | Identifiers |
|---|---|
| Installed-app identifiers with delete entries | 207 |
| Absent from the live list | 173 |
| Present in the live list | 34 |
Where this sits in the Lab's research
This contribution is the tooling side of Lab Technical Report LAB-TR-0009, Screen Time on iOS 15 to 27: Mostly Empty Usage Tables and Counts That Change Without the Write-Ahead Log, published on Zenodo (doi:10.5281/zenodo.23720067, version 1.2; the concept DOI 10.5281/zenodo.23717932 always points to the newest version). The report reads 17 stores from iOS 15.6 to 26.6.2, finds usage rows on 4, measures the log effect and analyzes the delete entries. Its eight file system artifacts are the ones described here.
No other Lab report covers this pull request yet; the method above is from the pull request and the report.
Sources
Every figure in the text and in the diagrams is listed here with where it comes from. Nothing else was used: no device, image or report was opened for this post.
| Number or claim | Source |
|---|---|
| 8 artifacts, +2,577 lines, 0 deleted, one new module | PR #2573 body and file list |
| Merged 25 October 2026 | PR #2573 state and mergedAt |
| Rows on three extractions: 1/1/1 for four artifacts; 336/0/0; 1/0/4; 0/0/4; usage 0 | PR #2573 body, checklist item 1 |
| Independent count(*) gives the same numbers; four deletes are four ZCHANGETYPE = 2 rows in one transaction | PR #2573 body, checklist item 1 |
| Earlier run on five extractions | PR #2573 body, checklist item 1 |
| Usage tables empty on all eight real devices; usage artifact unverified on real data | PR #2573 body, reviewer notes |
| Older iOS versions and iPad not verified | PR #2573 body, checklist item 1 |
| 12 unit tests; 16 of 16 test cases on a Windows host with an absolute temp folder; 26 of 26 CI jobs | PR #2573 body, test record |
| Two synthetic shapes: managed child with usage rows; plain unmanaged | PR #2573 body, reviewer notes |
| Passcode reported as present or absent; reduced to 0 or 1 in SQL | PR #2573 body; diff file screenTimeStore.py |
| Search pattern ends in RMAdminStore-*.sqlite*; only main files opened | Diff file screenTimeStore.py (paths and _stores) |
| 17 stores: settings 17, blueprint 16, history 12, installed apps 11, tombstones 8, usage 4 | LAB-TR-0009 section 4.1 and Table 4 |
| Reading without the log changed a count on 14 of 17 stores | LAB-TR-0009 abstract and section 4.3 |
| 218 delete entries, 207 identifiers, 173 absent from the live list, 34 present | LAB-TR-0009 section 4.4 |
| 136 of 136 counts equal independent SQL; schema error found on first run | LAB-TR-0009 section 4.7 |
| Display name empty on every row examined in set P | LAB-TR-0009 section 4.4 |
| Zenodo DOI 10.5281/zenodo.23720067 (version 1.2), concept 10.5281/zenodo.23717932 | papers/zenodo/DOIS.md |