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.

Synthetic filesFull file system layoutVersion 1.0Data CC BY 4.0Code MIT

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.

One case folder, and the top level of the zip
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
Files in each case and what they are modelled on
FileHoldsModelled on
accounts_ce.dbAccounts, authentication tokens (placeholders, marked as not real) and extras.ALEAPP accounts_ce and accounts_ce_authtokens read these tables
accounts_de.dbAccounts 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.listPackage 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.xmlPer-user package state, with first-install-time in hexadecimal Unix milliseconds.ALEAPP package_restrictions
install_sessions.xmlInstall sessions with created, updated and committed times in Unix milliseconds.ALEAPP install_sessions
notification_policy.xmlNotification 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.xmlOne saved network, with a creation time that has no year and no zone.ALEAPP WiFi Config Store
bt_config.confAdapter 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.dbPlay Store app state (first download, last update, account) and ownership (purchase time).ALEAPP installed apps (Vending and Library)
build.propInvented build identity.ALEAPP build
shared_prefs, Android/data foldersA 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.

Categories in DS-0003 and the reference answer for each
CategoryCasesSetupReference answerAction rows
Standard6Binary 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 XML4The 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 apps4One 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 mixes6Six 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 variants4WPA3 (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 script2The 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

Stores that still name the removed app, over the 24 handsets that ran the script
StoreHandsets where it still names the removed app
packages.xml package record0 of 24
packages.list line0 of 24
package-restrictions.xml entry2 of 24
install_sessions.xml record20 of 24
notification_policy.xml entry20 of 24
Play localappstate.db row16 of 24
Play library.db ownership row16 of 24
Usage statistics records2 with a readable name, 19 with the name gone, 3 pruned
Legacy domain-verification state in packages.xml20 of 24
settings_ssaid.xml entry0 of 24
settings_ssaid.xml.fallback entry2 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.

Action sheet for case v03-standard-03 and where each trace sits
RowActionTrue time (UTC)First trace, as storedFiles
P1Account added
synth.user29@example.test
2026-06-28 12:34:09.2351782650049235accounts_ce.db, accounts_de.db, usagestats/daily
P2First app installed and opened
org.synthlab.weatherbox
2026-06-28 12:44:39.70719f0e42b19binstall_sessions.xml, library.db, localappstate.db, package-restrictions.xml, packages.xml, usagestats/daily
P3Wi-Fi network joined
SYNTH-Home-Test
2026-06-28 12:54:30.220time=06-28 13:54:30.220WifiConfigStore.xml, usagestats/daily
P4Second app installed and opened
org.synthlab.calcpro
2026-06-28 13:04:51.3841782651891084install_sessions.xml, library.db, localappstate.db, usagestats/daily
P5Bluetooth headset paired
SYNTH Buds D4
2026-06-28 13:34:19.4301782653659bt_config.conf, usagestats/daily
P6Second app removed
org.synthlab.calcpro
2026-06-28 14:34:17.906(absent)packages.xml, settings_global.xml, usagestats/daily
P7Extraction taken2026-06-28 14:44:40.0442026-06-28T14:44:40ZSYNTHETIC.txt
accounts_de.db (read with a SQLite browser)
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
WifiConfigStore.xml (binary XML, shown as text; lines for the network)
<string name="ConfigKey">&quot;SYNTH-Home-Test&quot;WPA_PSK</string>
<string name="SSID">&quot;SYNTH-Home-Test&quot;</string>
<string name="CreationTime">time=06-28 13:54:30.220</string>
<boolean name="HasEverConnected" value="true" />
bt_config.conf (the section with a link key)
[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
packages.xml (binary XML, shown as text; the record of the app that stayed, attributes shortened)
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

reference_answers.json (excerpt)
{
  "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"
  ]
}
Stores in case v03-standard-03 and whether each still names the removed app after the removal
StoreStill names the removed app
packages.xml package recordno
packages.list lineno
package-restrictions.xml entryno
install_sessions.xml recordyes
notification_policy.xml entryyes
Play localappstate.db rowyes
Play library.db ownership rowyes
Usage statistics recordsunresolved
Legacy domain-verification state in packages.xmlyes
settings_ssaid.xml entryno
settings_ssaid.xml.fallback entryno
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.

  1. 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
  2. Unzip it and open one case folder. Do not open reference_answers.json yet. Note the stated extraction time in SYNTHETIC.txt.
  3. Open the accounts databases in DB Browser for SQLite or the sqlite3 shell. In accounts_de.db read last_password_entry_time_millis_epoch (Unix milliseconds) and the debug_table time (device wall clock). Which gives UTC without knowing the offset?
  4. 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.
  5. Find the apps. In packages.xml list the packages that start with org.synthlab and convert ut (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.
  6. 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?
  7. Read the Bluetooth file in a text editor. Which sections have a LinkKey and which do not? Is there a Timestamp?
  8. Compare with reference_answers.json: your timeline against actions, your list of files that name the removed app against removed_app_names_still_held_by.
  9. 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

10d935d1f25c698d67988265cb105f313cf7448823bfae88ea1ff4d139b169ed

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)

38e2bddc3a94a2058f29b0bd5a316d74a6e27516f52dd61e3464ccea46559574
Files in DS-0003 with SHA-256 hashes
FileContentSizeSHA-256
pixel-ffs-baseline-1.0.zipArchive440,095 bytes
10d935d1f25c698d67988265cb105f313cf7448823bfae88ea1ff4d139b169ed
reference_answers.jsonReference answers386,241 bytes
96523ab234c730d6f19fb5e44e00f95272508a72a7cfb6b219d806bacfe24e1f
reference_actions.csvReference answers (one row per case and action)34,883 bytes
195217636edc16086a63d2c32d57a53e97b720e0f931c002896272c617ad4eef
reference_residue.csvReference answers (one row per case and store)35,408 bytes
0171f72f07c391ef8427a75bddbb17f6df46734ca5e51d49d060b90424dd0bfe
README.txtNotes2,374 bytes
7e52fd4fe6f7815b545d803e11e1011418354056527c55ca90717ec278aab9a8
LICENCE.txtLicences1,544 bytes
f01e12484a8e1513424df9fd217ea96a9bc57399a5553967c35573dcd916b362
generator/generate.pyGenerator (MIT)65,384 bytes
4c8ea6d288ac2d45850f1e05b15712d357da60d38ca09757cbf0da1608ca8152
tools/abx_to_xml.pyBinary XML to text XML (MIT)6,217 bytes
b27e717aedd2ed37c275bac7cc45d49801b7a88a8db35777f2e17d75833f4a02
manifest.jsonManifest (file, bytes, SHA-256)134,694 bytes
38e2bddc3a94a2058f29b0bd5a316d74a6e27516f52dd61e3464ccea46559574
SHA256SUMS.txtThe same hashes in sha256sum format88,595 bytes
8b409ccc0c440e54b93582113a4e3f88c55a6820138cb715c9e39cf8550f3399
cases/ (676 files)Device folder trees3,022,632 bytesOne 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

Citation guide
BibTeX
@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

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.