DS-0003
Synthetic Pixel-class full file system baseline
26 device folder trees written by a script, in the layout an Android full file system extraction has and the public ALEAPP parser reads. Each is an invented Pixel-class handset after the same short script: an account added, two apps installed and one removed, a Wi-Fi network joined and a Bluetooth headset paired. Every case has reference answers, so you can test a parser against known actions before you trust it on a case. The values are invented and no file comes from a device.
Built from what the Lab learned on real devices provided to the Lab by partners; every file here is synthetic, so no case data is exposed.
At a glance
What the set is, how it was made, what it is not, and how it may be used.
The script, with t0 the first action: account added (t0), first app installed and opened (t0 + 00:10), Wi-Fi joined (t0 + 00:20), second app installed and opened (t0 + 00:30), headset paired (t0 + 01:00), second app removed (t0 + 02:00), extraction taken (t0 + 02:10). Each action lands up to 46 seconds after its nominal offset. Try the challenge: Same artifact, different Android versions (Practitioner). Also built on this set: What a missing setting means, Link records across stores.
- Device class
- None (generated files in a Pixel-class layout; an invented model, SYNTH Pixel-class)
- OS
- Android 16 class layout, invented build SYNTH.000000.000
- Evidence type
- Synthetic full file system folders
- Made on
- A script (generate.py, Python standard library) with seed 20261106. No device, no case data and no real identifiers. The same seed gives the same bytes, including the SQLite files.
- Contents
- 26 cases in 6 categories: 24 handsets that ran the script and 2 controls from before it. 170 rows in the action sheet, 676 files in the cases, 683 in the zip. 21 cases use Android binary XML, 5 use plain XML. 11 different clock offsets from UTC.
- Size
- 430 KB as a zip (440,095 bytes); 3.4 MB before compression
- Version
- 1.0
- Licence
- Data: CC BY 4.0. Code: MIT.
- Maintainer
- Daniel Addai, SectraTEK Lab
What is inside
One folder tree per case, laid out like a full file system extraction (system/, vendor/ and data/). Thirteen kinds of file carry the traces. The reference answers sit outside the case folders, so you can run a tool blind and compare after.
pixel-ffs-baseline/
README.txt LICENCE.txt
reference_answers.json reference_actions.csv reference_residue.csv
generator/generate.py tools/abx_to_xml.py
cases/
v03-standard-03/
SYNTHETIC.txt
data/data/com.android.vending/databases/library.db
data/data/com.android.vending/databases/localappstate.db
data/data/org.synthlab.weatherbox/shared_prefs/org.synthlab.weatherbox_preferences.xml
data/media/0/Android/data/org.synthlab.weatherbox/files/.synthetic
data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
data/misc/bluedroid/bt_config.conf
data/system/install_sessions.xml
data/system/notification_policy.xml
data/system/packages.list
data/system/packages.xml
data/system/users/0/package-restrictions.xml
data/system/users/0/settings_global.xml
data/system/users/0/settings_secure.xml
data/system/users/0/settings_ssaid.xml
data/system/users/0/settings_system.xml
data/system_ce/0/accounts_ce.db
data/system_ce/0/usagestats/daily/1782601200000
data/system_ce/0/usagestats/mappings
data/system_ce/0/usagestats/monthly/1780268400000
data/system_ce/0/usagestats/version
data/system_ce/0/usagestats/weekly/1782601200000
data/system_ce/0/usagestats/yearly/1767222000000
data/system_de/0/accounts_de.db
system/build.prop
vendor/build.prop
... 26 cases in all| File | Holds | Modelled on |
|---|---|---|
| accounts_ce.db | Accounts, authentication tokens (placeholders, marked as not real) and extras. | ALEAPP accounts_ce and accounts_ce_authtokens read these tables |
| accounts_de.db | Accounts with the last password entry time (Unix milliseconds) and the account service's debug table, whose time is a device wall-clock string with no zone. | ALEAPP accounts_de |
| packages.xml, packages.list | Package records with ft and ut times in hexadecimal Unix milliseconds and no it attribute, the installer, and the legacy domain-verification states. A removed app has no package record. | ALEAPP package_info and the orphaned-package-states artifact |
| package-restrictions.xml | Per-user package state, with first-install-time in hexadecimal Unix milliseconds. | ALEAPP package_restrictions |
| install_sessions.xml | Install sessions with created, updated and committed times in Unix milliseconds. | ALEAPP install_sessions |
| notification_policy.xml | Notification channels per package. | Layout is a model; ALEAPP is not needed to read it |
| settings_global / secure / system.xml, settings_ssaid.xml (and .fallback) | Device settings and the per-app Android ID entries. | ALEAPP settings and settings_ssaid |
| usagestats/ (mappings, version, daily, weekly, monthly, yearly) | Foreground events and per-package totals as protocol buffers, packages named through a token mapping. | ALEAPP usagestats, version 2 (token-mapped) layout |
| WifiConfigStore.xml | One saved network, with a creation time that has no year and no zone. | ALEAPP WiFi Config Store |
| bt_config.conf | Adapter lines, then one section per device the stack saved, with a Timestamp key in Unix seconds in some sections. | ALEAPP Bluetooth Connections and Bluetooth Adapter |
| localappstate.db, library.db | Play Store app state (first download, last update, account) and ownership (purchase time). | ALEAPP installed apps (Vending and Library) |
| build.prop | Invented build identity. | ALEAPP build |
| shared_prefs, Android/data folders | A placeholder file: the folder of an app exists or it does not. | Presence only |
Placement of each file inside the folder follows the paths the public ALEAPP artifacts match; it is a modelling choice, not a claim about every phone. Some content is background and not a script action: system packages and their usage records, and in some cases Bluetooth sections for devices that were only seen in a scan. A tool should not report these as script actions.
Sources for the formats: ALEAPP (MIT; its artifact notes cite the Android Open Source Project files they were read from), the Android reference UsageEvents.Event, the ABX reader bundled in ALEAPP (CCL Forensics), and Lab report LAB-TR-0035.
Reference answers
26 cases in 6 categories. For each case the set holds the files and a record of what was done: every action with its true time, the file and field where its trace sits and how the time is stored, what the removed app left in each store, and bounds on the removal time.
| Category | Cases | Setup | Reference answer | Action rows |
|---|---|---|---|---|
| Standard | 6 | Binary XML (ABX) as a recent Pixel-class build writes it. Both apps from the Play Store, the second removed from the package installer dialog (4 cases) or from the Play Store (2). | All seven rows of the action sheet with true time and the file where the time sits. The removed app is still named in five stores; its usage records have no readable name. | 42 |
| Plain text XML | 4 | The standard script and residue, with every system XML file in plain text (an older style of file). Removal from the dialog (2) or the Play Store (2). | The same answers as standard. A tool must read both XML forms. | 28 |
| Sideloaded apps | 4 | One or both apps installed by the package installer from the Files app, or one by adb. No Play Store rows for them. A removal by adb leaves no foreground event and has adb_enabled set. | The installer of each app, and which stores could never have held it. For the adb removal, bounds on the removal time only. | 28 |
| Residue mixes | 6 | Six different mixes of what the removed app leaves behind, from nothing at all (case 1) to nine stores (case 5), with the usage records named, unnamed or pruned. | Per store, whether the removed app is still named. In case 1 nothing names it and the answer says the set cannot show it was ever there. | 42 |
| Wi-Fi and Bluetooth variants | 4 | WPA3 (SAE) and open Wi-Fi, a hidden network, a name with an ampersand and quotes. Bluetooth scans that left sections for devices never paired, and a headset section with no Timestamp key. | The security type and hidden flag, which sections carry a link key (consistent with a bonded device) and which were only seen, and whether the pairing time is in the file. | 28 |
| Control: before the script | 2 | The imagined handset before anything was done: no account, no test apps, no saved network, no paired device. | Nothing was done. A tool that reports an account, a test app, a network or a paired device here is wrong. | 2 |
The answers are in reference_answers.json (one record per case), reference_actions.csv (one row per case and action) and reference_residue.csv (one row per case and store, for the removed app). A case record gives the clock offset used for wall-clock strings, the extraction time, both apps with their install and open times, the account, the Wi-Fi network, the Bluetooth sections (paired and only seen), the list of actions with their evidence (file, item, value as stored, time in UTC, role), what the removed app left behind, the bounds on its removal time, and expected_rows: the number of rows each public ALEAPP artifact should return.
What the removed app left behind
| Store | Handsets where it still names the removed app |
|---|---|
| packages.xml package record | 0 of 24 |
| packages.list line | 0 of 24 |
| package-restrictions.xml entry | 2 of 24 |
| install_sessions.xml record | 20 of 24 |
| notification_policy.xml entry | 20 of 24 |
| Play localappstate.db row | 16 of 24 |
| Play library.db ownership row | 16 of 24 |
| Usage statistics records | 2 with a readable name, 19 with the name gone, 3 pruned |
| Legacy domain-verification state in packages.xml | 20 of 24 |
| settings_ssaid.xml entry | 0 of 24 |
| settings_ssaid.xml.fallback entry | 2 of 24 |
| Shared-storage folder Android/data/<app> | 2 of 24 |
| App data folder data/data/<app> | 0 of 24 |
These counts describe this synthetic set, in which each case fixes one profile on purpose. They are not how often a real phone keeps each trace; for that see LAB-TR-0035. In 1 of the 24 handsets no store names the removed app at all.
Limits. No file in a case stores the removal time; the answers give a lower bound (the removed app's last foreground event, readable in 21 handsets, and with its name in 2) and an upper bound (the extraction time). Where the app was removed from the package installer dialog or the Play Store, a foreground event of that app a few seconds before the removal is an indicator, not proof; an adb removal has none. The Bluetooth Timestamp key equals the pairing time here; on a real phone the key can be rewritten when the stack saves the device again, so it need not. A section with a link key is consistent with a bonded device; a section without one does not show a pairing. A missing trace does not prove an action did not happen.
One case, read end to end
Case v03-standard-03: the standard script on a handset whose clock is UTC+01:00. The account service's debug time and the Wi-Fi creation time are device wall-clock strings with no zone (the Wi-Fi one has no year either); the other times are Unix values. The reference answer gives the true UTC time of each action. The second app was removed from the Play Store, so no store shows when.
| Row | Action | True time (UTC) | First trace, as stored | Files |
|---|---|---|---|---|
| P1 | Account added synth.user29@example.test | 2026-06-28 12:34:09.235 | 1782650049235 | accounts_ce.db, accounts_de.db, usagestats/daily |
| P2 | First app installed and opened org.synthlab.weatherbox | 2026-06-28 12:44:39.707 | 19f0e42b19b | install_sessions.xml, library.db, localappstate.db, package-restrictions.xml, packages.xml, usagestats/daily |
| P3 | Wi-Fi network joined SYNTH-Home-Test | 2026-06-28 12:54:30.220 | time=06-28 13:54:30.220 | WifiConfigStore.xml, usagestats/daily |
| P4 | Second app installed and opened org.synthlab.calcpro | 2026-06-28 13:04:51.384 | 1782651891084 | install_sessions.xml, library.db, localappstate.db, usagestats/daily |
| P5 | Bluetooth headset paired SYNTH Buds D4 | 2026-06-28 13:34:19.430 | 1782653659 | bt_config.conf, usagestats/daily |
| P6 | Second app removed org.synthlab.calcpro | 2026-06-28 14:34:17.906 | (absent) | packages.xml, settings_global.xml, usagestats/daily |
| P7 | Extraction taken | 2026-06-28 14:44:40.044 | 2026-06-28T14:44:40Z | SYNTHETIC.txt |
accounts_de.db accounts _id | name | type | last_password_entry_time_millis_epoch 1 | synth.user29@example.test | com.google | 1782650049235 accounts_de.db debug_table _id | action_type | time | table_name | caller_uid 1 | action_account_add | 2026-06-28 13:34:09 | accounts | 10120
<string name="ConfigKey">"SYNTH-Home-Test"WPA_PSK</string> <string name="SSID">"SYNTH-Home-Test"</string> <string name="CreationTime">time=06-28 13:54:30.220</string> <boolean name="HasEverConnected" value="true" />
[02:62:ef:54:0b:4a] Name = SYNTH Buds D4 DevClass = 2360324 DevType = 1 AddrType = 0 Manufacturer = 65535 LmpVer = 9 LmpSubVer = 0 MetricsId = 1 Timestamp = 1782653659 LinkKeyType = 4 PinLength = 0 LinkKey = 51dbb6dab142b12d42f291e6c650a346 Service = 0000110b-0000-1000-8000-00805f9b34fb
name="org.synthlab.weatherbox" ft="19f0e42ad4f" ut="19f0e42b19b" installer="com.android.vending"
What the reference answer says about the Wi-Fi join, the removal bounds and the leftovers
{
"case_id": "v03-standard-03",
"utc_offset_minutes": 60,
"actions[2]": {
"id": "P3",
"action": "wifi_network_joined",
"time_utc": "2026-06-28T12:54:30.220Z",
"evidence[0]": {
"file": "data/misc/apexdata/com.android.wifi/WifiConfigStore.xml",
"item": "WifiConfiguration CreationTime",
"stored": "time=06-28 13:54:30.220",
"time_utc": "2026-06-28T12:54:30.220Z",
"role": "primary",
"note": "device wall clock, no year and no zone recorded"
}
},
"actions[5].bounds": {
"not_before_utc": "2026-06-28T13:08:22.917Z",
"not_before_basis": "last foreground event of the removed app; readable only when usage_b is named or unresolved",
"last_use_time_readable": true,
"last_use_name_readable": false,
"not_after_utc": "2026-06-28T14:44:40.044Z",
"not_after_basis": "stated extraction time"
},
"removed_app_names_still_held_by": [
"install_sessions_record",
"notification_policy_package",
"play_localappstate_row",
"play_library_ownership_row",
"domain_verifications_legacy_user_state"
]
}| Store | Still names the removed app |
|---|---|
| packages.xml package record | no |
| packages.list line | no |
| package-restrictions.xml entry | no |
| install_sessions.xml record | yes |
| notification_policy.xml entry | yes |
| Play localappstate.db row | yes |
| Play library.db ownership row | yes |
| Usage statistics records | unresolved |
| Legacy domain-verification state in packages.xml | yes |
| settings_ssaid.xml entry | no |
| settings_ssaid.xml.fallback entry | no |
| Shared-storage folder Android/data/<app> | no |
| App data folder data/data/<app> | no |
The values are invented. In this case the removed app's usage records are still in the daily file, but the mappings file no longer names the package, so a reader shows an empty package name for them. Nothing in packages.xml names the app; the legacy domain-verification section still does.
Try it with free tools
Python 3, a SQLite browser and a plain text editor are enough. Nothing here needs a commercial tool.
- Check the download. Compute the SHA-256 of the zip and compare it with the value below:
python -c "import hashlib,sys;print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" pixel-ffs-baseline-1.0.zip - Unzip it and open one case folder. Do not open
reference_answers.jsonyet. Note the stated extraction time inSYNTHETIC.txt. - Open the accounts databases in DB Browser for SQLite or the
sqlite3shell. Inaccounts_de.dbreadlast_password_entry_time_millis_epoch(Unix milliseconds) and thedebug_tabletime (device wall clock). Which gives UTC without knowing the offset? - Read the binary XML. Most XML files here are Android binary XML. Run
python tools/abx_to_xml.py data/misc/apexdata/com.android.wifi/WifiConfigStore.xml. Plain text cases open in any editor. Find the creation time of the saved network and work out its UTC time from the offset in the answers. - Find the apps. In
packages.xmllist the packages that start withorg.synthlaband convertut(hexadecimal milliseconds):python -c "import datetime,sys;print(datetime.datetime.fromtimestamp(int(sys.argv[1],16)/1000,datetime.timezone.utc))" 19f0e42b19b(the value in v03-standard-03; use the one in your case). One of the two apps from the script is missing. - Look for the missing app elsewhere. Search the whole case folder for its package name (a text search over the decoded XML and the databases). Which files still name it? Which do not? Are its usage records there under an empty name?
- Read the Bluetooth file in a text editor. Which sections have a
LinkKeyand which do not? Is there aTimestamp? - Compare with
reference_answers.json: your timeline againstactions, your list of files that name the removed app againstremoved_app_names_still_held_by. - Optional. Point the public ALEAPP at a case folder. The Lab ran the parsing code of 14 ALEAPP artifacts (accounts, Bluetooth, Wi-Fi, install sessions, package restrictions, orphaned package states, installed apps from the Play Store, settings and Android IDs) over all 26 cases without its window, at commit 7bc49e3e of 24 October 2026. Row counts agree with
expected_rows, and four times (account added, first app install, install session, Bluetooth Timestamp) agree to the second. Usage statistics and package_info were not run there because the libraries they need were not installed; their expected counts are in the answers (usagestats_event_rows,package_info_rows).
Try the challenge: Same artifact, different Android versions (Practitioner). Also built on this set: What a missing setting means, Link records across stores.
Get the dataset
One zip, 440,095 bytes. It holds 683 files: the cases, the reference answers, the licences, a short README, the generator and a binary XML converter. Check it against the hash below.
Download pixel-ffs-baseline-1.0.zip (430 KB)
Served from this site, versioned. The manifest and the hashes are linked below.
SHA-256 of the zip
The loose files, manifest.json and SHA256SUMS.txt sit beside the zip on this site. To rebuild every byte yourself, run python generate.py from the generator folder (Python 3, standard library only).
Licence
Data: Creative Commons Attribution 4.0 (CC BY 4.0)
A plain-language summary. The full text is at creativecommons.org/licenses/by/4.0 and in LICENCE.txt inside the zip.
You may
- copy and share the files in any medium or format;
- adapt them, for example to make test fixtures, and use them for any purpose, including teaching, research, casework and commercial work.
You must
- give credit, using the citation on this page;
- link to the licence and say if you changed the files.
Please also
- keep the hashes beside any copy you share, so others can check it;
- say that the files are synthetic. Do not present them as taken from a real phone or a real case. They are not.
Code: MIT
generate.py and abx_to_xml.py are under the MIT licence. Keep the copyright notice with copies.
The dataset is provided as is, without warranty.
Hashes
Check every file after download. The set hash is the SHA-256 of manifest.json, which lists the size and hash of every other file.
Set hash (SHA-256, manifest.json)
| File | Content | Size | SHA-256 |
|---|---|---|---|
| pixel-ffs-baseline-1.0.zip | Archive | 440,095 bytes | 10d935d1f25c698d67988265cb105f313cf7448823bfae88ea1ff4d139b169ed |
| reference_answers.json | Reference answers | 386,241 bytes | 96523ab234c730d6f19fb5e44e00f95272508a72a7cfb6b219d806bacfe24e1f |
| reference_actions.csv | Reference answers (one row per case and action) | 34,883 bytes | 195217636edc16086a63d2c32d57a53e97b720e0f931c002896272c617ad4eef |
| reference_residue.csv | Reference answers (one row per case and store) | 35,408 bytes | 0171f72f07c391ef8427a75bddbb17f6df46734ca5e51d49d060b90424dd0bfe |
| README.txt | Notes | 2,374 bytes | 7e52fd4fe6f7815b545d803e11e1011418354056527c55ca90717ec278aab9a8 |
| LICENCE.txt | Licences | 1,544 bytes | f01e12484a8e1513424df9fd217ea96a9bc57399a5553967c35573dcd916b362 |
| generator/generate.py | Generator (MIT) | 65,384 bytes | 4c8ea6d288ac2d45850f1e05b15712d357da60d38ca09757cbf0da1608ca8152 |
| tools/abx_to_xml.py | Binary XML to text XML (MIT) | 6,217 bytes | b27e717aedd2ed37c275bac7cc45d49801b7a88a8db35777f2e17d75833f4a02 |
| manifest.json | Manifest (file, bytes, SHA-256) | 134,694 bytes | 38e2bddc3a94a2058f29b0bd5a316d74a6e27516f52dd61e3464ccea46559574 |
| SHA256SUMS.txt | The same hashes in sha256sum format | 88,595 bytes | 8b409ccc0c440e54b93582113a4e3f88c55a6820138cb715c9e39cf8550f3399 |
| cases/ (676 files) | Device folder trees | 3,022,632 bytes | One hash per file in manifest.json and SHA256SUMS.txt |
The zip holds the same files as the folder (the zip itself, manifest.json and SHA256SUMS.txt excepted). Together the files are 3,554,683 bytes before compression. Hashes and sizes on this page are read from manifest.json.
Cite this dataset
Cite as
Addai, D., SectraTEK Lab (2026). Synthetic Pixel-class full file system baseline (DS-0003), version 1.0. SectraTEK Lab Datasets. https://lab.sectratek.com/datasets/pixel-ffs-baseline/ SHA-256 of manifest.json 38e2bddc3a94a2058f29b0bd5a316d74a6e27516f52dd61e3464ccea46559574
@dataset{sectratek-lab-ds-0003,
author = {Addai, Daniel},
title = {Synthetic Pixel-class full file system baseline},
year = {2026},
version = {1.0},
publisher = {SectraTEK Lab},
url = {https://lab.sectratek.com/datasets/pixel-ffs-baseline/},
note = {DS-0003, SHA-256 of manifest.json 38e2bddc3a94a2058f29b0bd5a316d74a6e27516f52dd61e3464ccea46559574}
}Related
- Report: Where removed apps leave tracesA per-store measurement on real Android and iOS extractions; this set applies one profile per case
- Dataset: Synthetic recovery-history setThe Android-side synthetic set built the same way
- Dataset: iPhone sysdiagnose-style setThe iPhone counterpart, with the same script idea
Datasets carry their own licence. This one is CC BY 4.0 for data and MIT for code. Articles are CC BY 4.0. All licences.