Lab Technical Report LAB-TR-0001
Making Silent Failures Visible: A Single-Pass Section Reader for Android Bug Reports
SectraTEK Lab, Prudential Associates
research@sectratek.com
Lab Technical Report, preprint, not peer reviewed
Version 1.1 · 27 October 2026 · CC BY 4.0 · doi:10.5281/zenodo.23717909
Abstract
Android bug reports bundle the dumps of hundreds of system services and several logs into one text file that can exceed two million lines. A parser of such a file can fail silently: records lost to a misread line, a service dump the platform stopped at its time limit, and a section no parser reads all appear as the same short or empty table. We present a single-pass section reader that enters every section in an index, stores the time limit on each service dump the platform cut short, and passes each section's lines only to its registered parsers, which feed 158 artifacts. On seven real reports from four vendor families (Android 10, 15 and 16), a full run took 20 to 55 s with a peak of at most 585 MB, and raw-text counts and a second, separately implemented parser agreed with the reader on every artifact compared, apart from small, explained differences. Validation exposed the first cause: before a fix, one damaged line reduced 284 packages to 15 without an error. The index separates the other two causes and shows that about 80 percent of the sections of two reports are read by no artifact.
CCS Concepts • Applied computing → System forensics.
Keywords Android bug report, dumpstate, dumpsys, digital forensics, silent failure, parser validation, tool testing, single-pass parsing
ACM Reference FormatDaniel Addai. 2026. Making Silent Failures Visible: A Single-Pass Section Reader for Android Bug Reports. Lab Technical Report LAB-TR-0001, version 1.1. SectraTEK Lab, Prudential Associates. Preprint, not peer reviewed. https://lab.sectratek.com/research/reports/lab-tr-0001/ DOI: https://doi.org/10.5281/zenodo.23717909
1 Introduction
An Android bug report is the platform's own snapshot of a device. It is a zip archive whose main member is a plain-text file holding the output of dozens of commands, the dumps of every system service and several logs [1], [4]. It can be produced with the standard debugging command adb bugreport [9], and it records what examiners ask about every day: installed packages, permission and app-ops state, battery history, network and radio state, accounts and sync, alarms and jobs, process exits, and crash and boot records. On current devices the main file reaches two million lines or more, so examiners depend on parsers to read it.
A motivating failure. A parser of this file can lose most of a table without any sign that it did. During the validation reported here, a single damaged line at column 0 inside the package dump made our own parser end the package list early (Listing 1). The run completed and the package table had rows, yet only 15 of the report's 284 packages remained. The parser was tolerant by design, and that tolerance hid the loss: such a failure is visible only to a check that counts the records in the text by other means.
Listing 1: Schematic of the damaged-line failure: a damaged line at column 0 is read as a new heading, and the packages after it are dropped (invented names; content shortened).
Packages:
Package [org.example.alpha] (...):
versionName=...
#&!x? <- read as a heading
Package [org.example.beta] (...): <- dropped
Package [org.example.gamma] (...): <- droppedThe problem: silent partial parsing of bug reports. The example is one instance of the problem this report addresses. A bug report does not announce what it lacks, and a parser of it does not usually announce what it skipped. Three different causes produce the same visible result, a short or empty table: the parser misread the text; the platform stopped a slow service dump at its time limit, so the data were never written; or no parser reads that section at all. An examiner who sees an empty table therefore cannot tell absence of data from failure to read it.
Approach. We built a reader that makes these failures visible and then measured what it showed. The section reader (hereafter the reader) passes over the report once, enters every section in an index, records each service dump the platform timed out, and hands the lines of each section only to the parsers registered for it. Its output feeds artifacts: an artifact is a parser module that presents one kind of record as a table in the tool's report. We ask four research questions.
- RQ1 (Scale). Can every section of a multi-million-line report be indexed, and the commonly used ones parsed, in one pass, in bounded memory and tens of seconds?
- RQ2 (Fidelity). How closely do the parsed rows agree with the raw text, measured by independent counts and a second, separately implemented parser?
- RQ3 (Robustness). Which failure classes appear on real and altered input that tests on synthetic text did not reveal?
- RQ4 (Visibility). How much of a report is read by no artifact, and which service dumps did the platform time out?
Contributions. This report makes four contributions.
- A threat model of silent failure in bug report parsing: four failure classes, how each appears in the output, and the signal that exposes it (Section 3.1).
- A single-pass reader that builds a complete section index and records time-limit cuts in the same pass that parses the report, and 158 artifacts in 22 groups built on it (Sections 3.2 to 3.5).
- A validation on seven real reports from four vendor families covering run time, memory, agreement with raw-text counts and with a second, separately implemented parser, and 13 altered-input variants (Sections 4 and 5.1 to 5.3).
- Seven reader defects found by that validation, including the damaged-line failure, and a measured coverage gap: about 80 percent of the sections of two reports have content that no artifact reads (Sections 5.4 and 5.5).
Scope. The contribution is engineering and validation, not a new parsing algorithm: the section grammar is the one the platform prints (Section 2.1). All results hold for the seven reports tested; we made no comparison with other tools, so the report makes no claim of speed or coverage relative to them. Section 7 states the limits. Section 2 positions the work, Section 3 presents the threat model and the design, Section 4 the evaluation method, Section 5 the results, and Section 6 what they mean for telling absent data from unread data.
2 Background and Related Work
This section describes the format the reader parses and places the work among three kinds of existing tools: tools that extract selected structures, indicator matchers, and generic log parsers. It closes with work on validating forensic tools.
2.1 The bug report format
Since Android 7 the bug report is a zip written by the dumpstate service: a main text member, a version.txt naming the format version, optional copies of device files under FS/, and from Android 9 per-service protocol buffer files [1]. The format document specifies the archive, not the text headers described next, which we took from the reports and from the platform sources.
The main text opens with a banner and header lines and then repeats two kinds of block. A command section starts with ------ TITLE (command) ------ and ends at a duration line (was the duration of 'TITLE'). A service section starts with DUMP OF SERVICE name: and ends at a line that names the service and the time its dump took. A section still open at the next header ends there. Dumpstate runs service dumps under time limits that differ by priority: 500 ms for critical services and 10 s for normal ones in the source we read [2]. When a dump exceeds its limit, the dumpsys tool prints a marker of the form *** SERVICE 'name' DUMP TIMEOUT (N ms) EXPIRED *** [3], with or without a space before ms (for example (500ms) or (500 ms)), and the reader accepts both forms; the same source prints the service header and the closing duration line. We call such a section a timed-out dump. The limits observed in our reports (Section 5.5) match these values. The platform's guide to reading bug reports recommends searching the file with text tools and lists the sections it considers most useful; it states retention windows for some content, such as the last 300 foreground and 300 background broadcasts, but does not describe the time-limit marker [4].
2.2 Tools that extract selected structures
Most public tools extract a chosen set of structures and present them; Table 1 lists them with their documented scope, checked against the project pages on 2026-10-27. Battery Historian turns the battery data of a report into a timeline and aggregated statistics [8]. dumpstate-py extracts 15 structures [6], and bugreport-extractor-library provides 18 parsers with timeline export [12]. ALEAPP parses on-disk artifacts of Android device extractions; by a name scan of its public tree on 2026-10-25, it had no bug report artifact before this work [5].
2.3 Indicator matchers
A second group reads a report to decide a question, typically whether a device shows signs of compromise. MVT documents a command that checks a standalone bug report [13], [15] and notes that report formats vary across Android versions and vendors, which limits what can be checked [14]; bugreport-extractor-library also offers detection features [12]. A matcher needs only the sections its indicators use, so its coverage is defined by its rules rather than by the report.
2.4 Generic log parsers
Log parsing research turns free-text log messages into structured events by separating a constant template from variable parameters. Drain parses a log stream online with a fixed-depth tree [10], and Zhu et al. benchmark automated log parsers for accuracy, robustness and efficiency [16]. These methods suit line-oriented logs such as those inside a bug report, but a bug report as a whole is a container of heterogeneous dumps whose block structure is fixed by the platform. Our problem is not to infer templates; it is to know which blocks were read, which were cut, and which were never examined.
| Tool | Category | Language, licence | Documented scope | Ref. |
|---|---|---|---|---|
| Platform guide | Manual reading | Documentation | Text search: logcat, ANR, activity, memory, power and package sections | [4] |
| Battery Historian | Selected structures | Go (build instructions), Apache-2.0; archived 2022-12-29 | Timeline of system and app events, aggregated battery statistics, comparison of two reports | [8] |
| dumpstate-py | Selected structures | Python, Apache-2.0 | 15 structures: header, battery, mount points, netstat, packages, processes, power reset reason, account service, keyguard service, crash info, kernel modules, socket state, network device info, GPS coordinates, USB | [6] |
| bugreport-extractor-library | Selected structures; indicators | Rust, Apache-2.0 | 18 parsers (header, memory, package, power, process, USB, Samsung SFS logs, battery, crash, network, Bluetooth, device policy, ADB, authentication, account, VPN, logcat, privacy), timeline export, detection features | [12] |
| MVT | Indicators | MVT License (an adaptation of the Mozilla Public License 2.0 with a consensual-use clause) | check-bugreport for a standalone report; detection of compromise; formats vary by version and vendor | [13], [14], [15] |
| ALEAPP | Extraction parser | Python, MIT | Artifact parsing of extractions; no bug report artifact before this work (name scan, 2026-10-25) | [5] |
Position of this work. None of the pages we read states which sections its tool leaves unread or how it treats a timed-out dump. That is a statement about the documentation, not evidence about the tools' behaviour. This work differs in what it reports rather than in how it parses: the reader presents a broad set of sections without judging them, and it reports what it did not read.
2.5 Validating forensic tools
Garfinkel argued that the field needs standardized, modular approaches to data representation and forensic processing [7]. Horsman describes the lack of adequate testing standards for forensic tools and reports a practitioner survey on tool reliability [11]. Both motivate the emphasis here: a parser's output is a claim that needs an independent check, and the check should be reported with its limits.
3 Design
This section defines silent failure, then describes how the reader passes over a report, indexes it, bounds its memory and presents rows.
3.1 Threat model: silent failure
We define a silent failure as a run that completes without error and produces plausible output, while records present in the input are missing from the output and nothing in the output says so. The threat is not an attacker but ordinary conditions: damaged or unusual lines, vendor variation in layout, platform time limits, and the finite scope of any tool. We do not model deliberate anti-forensic manipulation of a report beyond the altered inputs of Section 5.3. Table 2 lists the four classes we consider and what makes each visible in this work.
| Class | Cause | How it looks | Signal in this work |
|---|---|---|---|
| S1 Parse loss | The parser misreads a line and drops or misplaces later records | Fewer rows, no error | Not detected at run time; exposed in validation by independent counts and altered inputs (Section 4.2) |
| S2 Timed-out dump | The platform stopped a service dump at its time limit | Short or empty section | Section index stores the limit; an artifact with rows in the section logs it once (Section 3.3) |
| S3 Non-coverage | No artifact reads the section | Section absent from the output | Sections artifact lists every section and marks those no artifact reads (Section 3.3) |
| S4 Unreadable input | File ends early, or text in an encoding that is not read | Fewer or no rows | Partial: complete records up to a truncation; a UTF-16 text yields no rows, a stated limit (Section 3.4) |
3.2 Single-pass reader
The reader streams the main text once, line by line, from the zip member or from a plain text file (Figure 1). It splits lines on the line-feed byte only, so its line numbers match those of a text editor. A line is tested as a possible section boundary only when its first byte is one of -, D, = or *; any other line is decoded only if the open section has registered parsers, and is otherwise skipped (Listing 2). Section parsers are subclasses of one base class and register under the name of the section they read. At the end of the pass the parsed report is kept in a cache of six reports, so the artifacts that follow read tables, not text.
Listing 2: One pass over a report (simplified).
for each raw line (split on LF, cut at 1 MiB):
if first byte in {'-', 'D', '=', '*'}:
if duration line of the open section:
close the section, record its seconds
elif command header '------ T (cmd) ------':
close open sections; open command T;
create its parsers
elif 'DUMP OF SERVICE name:':
close the open service; open service name
elif line holds 'DUMP TIMEOUT (Nms)' or '(N ms)':
mark the open service as timed out at N ms
elif '== ' marker line:
close the command; note the marker
else:
pass the line to the open parsers
elif the open section has parsers:
decode the line; pass it to the parsers
else:
skip (no decoding, nothing kept)3.3 Section index and timeout detection
The section index is what turns silence into a visible record. Every section, whether or not a parser wants it, is entered with its kind (command or service), name, first and last line and printed duration. If the open service contains the time-limit marker, the limit in milliseconds is stored on that section. An artifact that has rows inside a timed-out dump logs the timeout once, and the index shows timeouts for all sections. A timed-out section is therefore never presented as complete, and an empty artifact can be read together with the index to tell an absent section from an unread one. The index is itself presented as an artifact, the Sections artifact, which marks each section that no artifact reads.
3.4 Bounds
Memory is bounded by caps rather than by streaming rows to disk. Each table keeps at most 500,000 rows and logs when it reaches the cap; a line longer than 1 MiB is cut without being held, and a decoded line is cut to 65,536 bytes. Bytes are decoded as UTF-8, with invalid sequences replaced, and CRLF line ends are removed. A text that begins as UTF-16 is not read. The largest table on any of the seven reports holds 405,850 rows (the system log of the largest report), below the cap.
3.5 Presentation rules
The 158 artifacts fall into 22 groups and follow one rule set. Values are shown as printed, including device identifiers. A time is shown as printed, and a UTC value is added only if the report itself records a time zone. The platform's “no time” values (1970-01-01 and 1969-12-31 23:59:59) are flagged, not converted. Nothing is rated, scored or judged. Each artifact states its evidence tier: data-proven on a stated number of real reports, constructed on synthetic text only, or not examined.
4 Evaluation Method
This section describes the evidence, the five checks that answer the research questions, what counts as the reference, and how time and memory were measured.
4.1 Evidence
The evidence is seven real bug reports from four vendor families, identified only by class and labelled R1 to R7 in order of zip size (Table 3). Three families contribute one report each (Android 10 and 15); the fourth contributes four Samsung reports (Android 16). All seven reports are in a UTC+0 time zone. We also used synthetic fixtures with invented values: per-artifact zips and text (about 17 MB of test data) and ten folders of test cases.
| Report | Vendor family | Android | Zip (MiB) | Sections | Text lines | Wall (s) | Peak (MB) |
|---|---|---|---|---|---|---|---|
| R1 | Transsion-brand | 10 | 5.4 | 343 | 487 k | 20.1 | 261 |
| R2 | Huawei | 10 | 6.7 | 410 | 495 k | 20.4 | 260 |
| R3 | Motorola | 15 | 16.6 | 539 | 1.65 M | 32.2 | 343 |
| R4 | Samsung A-series | 16 | 18.6 | 681 | 1.44 M | 46.5 | 494 |
| R5 | Samsung A-series | 16 | 22.3 | 609 | 1.80 M | 51.8 | 561 |
| R6 | Samsung A-series | 16 | 29.1 | 672 | 1.88 M | 46.9 | 477 |
| R7 | Samsung S-series | 16 | 34.2 | 656 | 2.16 M | 55.4 | 585 |
Zip sizes in MiB (1,048,576 bytes). Text lines are line feeds in the main member. Sections are the rows of the Sections artifact. Wall time includes tool start-up and the HTML, TSV and LAVA output of all artifacts. R4 and R6 were added last; the checks on five reports use R1 to R3, R5 and R7.
4.2 Validation checks
Five checks answer RQ1 to RQ3; a coverage measure answers RQ4.
- Independent counts. Row counts recomputed by code that does not use the reader and applies different rules: indentation trees, regular expressions, and raw line counts with a stream tool.
- Second parser. A field-by-field comparison with a second, separately implemented parser. It was written by the same team, is not part of the open-source project, and implements the same extraction by a different method.
- Whole-tool runs. All artifacts on each real report, with wall time and peak memory (Section 4.4).
- Altered inputs. Variants of one real text (R1): empty, truncated, damaged, re-encoded, and repeated twelve times, each with an outcome set in advance.
- Leak scan. Every token and long line of every test fixture compared against the real reports.
Each artifact was first developed in one of eight topic-specific, AI-assisted development streams, which recorded the row counts their artifacts produced on five reports. We call these the development-time counts and compare the final reader against them to detect changes made during integration. For RQ4 we define the coverage gap u of a report with section set S as the share of sections that have content but that no artifact reads (Equation 1). A section has content if it has at least one line; group headings are excluded from the numerator.
4.3 Reference values
No device-side reference exists for these reports: they were captured by others, and we do not know what the devices did. What can be established is agreement with the printed text. The reference for a count is therefore the count made by an independent method on the same text, and for a field, the value produced by the second parser. Both establish consistency of reading, not the correctness of the platform's own output.
4.4 Environment and measurement
All runs used Windows with Python 3.13 and the pytz package on one workstation whose specification was not recorded; the changed files were also parsed for Python 3.11 syntax. Whole-tool runs used the folder input mode (-t fs), which lets the tool see the zip as a file, as the tombstone and ANR members inside the zip require; the zip mode reads only the main text. Wall time is the elapsed time of the whole command. Peak memory is the largest commit peak of one process in a Windows job object; the launcher starts a child process, and the job total is about 10 MB higher. The measurements were taken on the combined code before it was divided into seven separately released changes, and were not repeated on the divided code (Artifact Availability).
5 Results
The reader processed each report in under a minute, agreed with independent counts, and exposed failures that synthetic tests had not. Table 4 answers each research question; the subsections give the evidence.
| Question | Answer | Evidence |
|---|---|---|
| RQ1 Scale | Yes. A full run of 158 artifacts took 20.1 to 55.4 s with a peak of 260 to 585 MB; tool start-up alone took 10.4 s. | Sec. 5.1, Table 3, Figures 2 and 3 |
| RQ2 Fidelity | Rows agree with raw-text counts (26 of 26) and with the second parser on every artifact compared, except three multi-line settings values and one section end on two reports; 740 of 745 counts reproduce the development-time counts. | Sec. 5.2, Table 5 |
| RQ3 Robustness | 12 of 13 altered inputs met their expected outcome; validation found seven defects, the costliest silently removing 269 of 284 packages; one loss remains unexplained. | Sec. 5.3 and 5.4, Tables 6 and 7 |
| RQ4 Visibility | About 80 percent of sections (546 of 681 on R4, 544 of 672 on R6) have content that no artifact reads; the index exposed one timed-out dump on R4 and four on R6. | Sec. 5.5, Tables 8 and 9, Figures 4 and 5 |
5.1 Scale (RQ1)
A full run of all 158 artifacts took 20.1 to 55.4 s with a peak of 260 to 585 MB (Table 3, Figure 2). Cost grows with report size but less than in proportion: R7 is 6.3 times larger than R1, took 2.8 times as long and used 2.2 times as much memory. Every run ended with exit code 0, no traceback and no error line. On R4 and R6, at least 148 of the 158 artifacts wrote rows, and each run produced more than half a million rows (509,574 and 520,876).
Fixed costs dominate the pass. A run on empty input took 10.4 s (Figure 3). On five reports, runs with 4, 9 and 158 artifacts took 11.6 to 12.4 s, 12.2 to 15.2 s and 20.1 to 55.4 s; peak memory on R5 rose from 241 to 261 to 561 MB. Because the three profiles used different output settings, the steps are not a clean measure of reading cost. The one direct measure comes from the permissions parsers, which added about 0.45 s to the pass (1.36 to 1.81 s) on one report of 214 MB and 2.2 million lines.
To test scale beyond the real reports, we repeated the text of R1 twelve times (about 5.8 million lines) and ran the nine-artifact profile. Row counts scaled exactly: 118,092 usage events (12 × 9,841), 10,224 package times (12 × 852) and 3,408 packages (12 × 284), with one set of device facts. Wall time rose from 12.2 to 24.1 s and peak memory from 244 to 318 MB. This is a synthetic repetition with nine artifacts, not a run of 158 artifacts on a 5.8-million-line report.
5.2 Fidelity (RQ2)
The reader's rows agree with every independent measure we applied, and each difference has an identified cause (Table 5). Against the development-time counts, 740 of 745 artifact-by-report counts were equal (149 artifacts on five reports). The five differences are one row in the Bluetooth adapter artifact on each report: an adapter address row added after those counts were recorded, when identifier masking was removed. For the first nine artifacts, the reader and the second parser agreed on package, package-time, usage-event, process-exit and boot-history counts and on all compared fields, including UTC values, on all five reports. They differed in two places only: three settings values that span several lines, which the two parsers split differently (the reader's choice is deliberate), and one statistics dump whose last line the two rules place one line apart on two reports. Raw-text counts of the 13 largest artifacts on R4 and R6 matched in 26 of 26 comparisons, and identifier rows equal a raw-text count on all seven reports.
| Comparison | Reports | Result |
|---|---|---|
| Artifact-by-report row counts against development-time counts | 5 | 745 compared, 740 equal; 5 differ by one added row (Bluetooth adapter address) |
| Packages and package times against the second parser | 5 | 0 package mismatches; time multisets equal; stamp sets equal |
| Usage events, process exits, settings changes, boot history against the second parser | 5 | Counts, fields and UTC values equal |
| Settings entries against the second parser | 5 | 3 entries differ (values over several lines, read differently on purpose) |
| Section index against the second parser | 5 | Equal on 3; on 2, one section ends one line apart |
| 13 largest artifacts against raw-text counts | 2 | 26 of 26 equal |
| Exported TSV rows against reader rows | 5 | Equal for the artifacts checked (device facts, packages, package times, usage events, process exits, settings, settings changes) |
| Identifier, command-line and bootconfig rows against raw-text counts | 7 | Equal (31, 7 and 306 rows) |
The second parser leaves UTC blank without the tzdata package on Windows, so its comparisons used a time zone patched to UTC+0. Because all reports are in UTC+0, the conversion was the identity on real rows; offsets and daylight-saving transitions are covered only by constructed text.
5.3 Robustness on altered input (RQ3)
Twelve of the thirteen altered inputs gave the outcome set in advance (Table 6). A text truncated inside the package dump yielded the complete packages before the cut (105 of 284) and nothing from later sections; a byte order mark, Latin-1 and CRLF line ends gave the base rows. A UTF-16 text yields no rows, which we record as a limit. One variant failed its expectation: with lone carriage returns, form feeds and NUL bytes injected, package times fell from 852 to 850 and usage events from 9,841 to 4,884. We have not determined which injected characters caused the loss, so it is not yet classified as a defect or as intended handling of damaged lines.
| Variant | Expected | Observed | Met |
|---|---|---|---|
| Empty file | No rows, no error | No rows, no error (10.4 s) | Yes |
| Banner only | No rows except report facts | 3 fact rows, 1 section row | Yes |
| Truncated at half | No error; rows not above base | 259 sections, 284 packages, no usage events | Yes |
| Truncated to a few lines | No error | 13 fact rows, 3 sections | Yes |
| Truncated inside the package dump | Complete packages before the cut | 105 packages, 315 package times | Yes |
| CRLF line ends | Same rows as base | Same rows | Yes |
| Latin-1; UTF-8 with byte order mark | Same rows as base | Same rows (both) | Yes |
| UTF-16 header | Not read, no rows | No rows | Yes (limit) |
| Times near 1969 to 1973 | Same rows; edge handling | Same rows; unset times flagged, no UTC | Yes |
| One very long line | Same rows, bounded memory | Same rows; 243 MB peak | Yes |
| Text repeated 12 times | 12 × rows, one set of facts | 12 × rows; 24.1 s, 318 MB | Yes |
| Lone CR, form feed and NUL injected | Same package and time rows | 850 of 852 package times; 4,884 of 9,841 usage events | No |
5.4 Defects found (RQ3)
Real-data and altered-input testing found seven reader defects (Table 7). One (the lost last exit entry) was found by a unit test written during that testing; the validation log does not record which of the others came from real data and which from the variants. Defect 3 is the motivating failure of Section 1: a damaged line at column 0 was read as a heading, and 284 packages became 15. Only two defects (4 and 5) raised an error; the consequence of each of the other five was wrong or missing output. After the fixes, 505 unit tests of the bug report modules and 1,025 case checks passed, as did a lint check of the changed code.
| No. | Defect | Consequence and fix |
|---|---|---|
| 1 | The activity service is dumped twice; the timeout marker was stored by name | Marker attached to the wrong dump; now stored on the section |
| 2 | The last exit entry of a dump was not flushed at section end | One entry lost per dump (found by a unit test) |
| 3 | One damaged line at column 0 in the package dump was read as a heading | All later packages lost (284 rows became 15); a heading must now end with a colon |
| 4 | A time at the calendar edge (year 1 or 9999) in the zone conversion | Overflow error; now no UTC value and a note |
| 5 | Non-ASCII digits (such as superscripts) passed a digit test | Crash on integer conversion; ASCII digits only |
| 6 | Multi-line settings values: trailing tokens are on the last line | Value split wrongly; earlier words now belong to the value |
| 7 | A pending-events list with 1970 times in the usage dump was read as events | False events; the list is not read and the note says so |
5.5 What the reader does not read (RQ4)
The index exposed timed-out dumps on both reports added last (Table 8). R4 had one (activity, 500 ms); R6 had four (activity at 500 ms; cacheinfo, dbinfo and resources at 10,000 ms). The tool logged the timeout of dbinfo, because an artifact has rows inside it. It did not log the timeout of activity on R4, because the affected artifact (process exits, 3,319 rows) takes its rows from a part outside the timed-out dump, and that count equals the number of exit entries in the text. No artifact reads cacheinfo or resources. In each case the index shows the timeout without the examiner reading the log.
| Report | Service | Limit (ms) | Read by an artifact |
|---|---|---|---|
| R4 | activity | 500 | Yes (rows from outside the timed-out part) |
| R6 | activity | 500 | Yes |
cacheinfo | 10,000 | No | |
dbinfo | 10,000 | Yes (timeout logged) | |
resources | 10,000 | No |
Coverage is the larger gap. The 158 artifacts fall into 22 groups of 2 to 16 artifacts, chosen by the question an examiner asks (for example “Network” or “Accounts, Sync and Backup”) rather than by section name (Figure 4). Even so, about four in five sections with content are read by no artifact on R4 and R6 (Table 9, Equation 1). The largest unread sections are the application provider and service dumps and the binder state (Figure 5). The measure counts sections by their lines; whether those lines hold evidence is a separate question that we did not examine.
| Quantity | R4 | R6 |
|---|---|---|
| Sections in the index, |S| | 681 | 672 |
| Marked “not read” by the Sections artifact | 568 (83.4%) | 564 (83.9%) |
| of which group headings | 3 | 3 |
| of which without a line of their own | 19 | 17 |
| Unread sections with content (coverage gap u) | 546 (80.2%) | 544 (80.9%) |
6 Discussion
The results say less about speed than about silence. This section draws three lessons and states what the evidence does not support.
6.1 Tolerant parsers can fail silently
The most consequential result is defect 3. A parser built to tolerate odd lines turned one damaged line into the loss of 269 of 284 packages, and the run still looked successful. Of the seven defects, only the two that raised an error announced themselves. Error handling therefore does not reveal parse loss; comparison does. We recommend a simple test to tool builders and testers: damage one line in a large section of a real report and compare the row count with that of the clean text. The altered-input variant that still fails its expectation (Table 6) shows that our own set of such tests is not exhausted.
6.2 An empty table is ambiguous without an index
Timed-out dumps occurred on both reports added last, including dumps that no artifact reads. Without the index, a short table from a timed-out dump cannot be told apart from a quiet device. With it, the examiner can separate three cases: the platform wrote nothing, the platform stopped writing, or the tool did not read. The index is built in the same pass as the parsing, so it needs no second reading of the file.
6.3 Coverage should be a reported quantity
Even this broad tool leaves most of a report unread: four in five sections with content on R4 and R6, including the largest. We do not claim that the unread sections matter to examiners, nor that they do not; the figure measures what the tool does not present, not what an examiner misses. Its value is that it is stated. A tool that reports its coverage gap lets an examiner decide where to read by hand, and lets two tools be compared on a defined quantity.
6.4 What the evidence does not show
Agreement with independent counts shows that the reader does what its specification says: a row is a record that the report printed. It does not show that the report is a correct account of the device, nor that the specification captures what the platform meant by its output. The 740 of 745 result compares the final reader with the development-time counts, so it shows that later integration, identifier and category changes did not alter rows, apart from one deliberate change. The work cannot be ranked against the tools in Table 1: they extract selected structures or match indicators, while this reader presents a broad set without judgement and reports what it did not read. A comparison needs a defined task and metric (Section 8).
7 Threats to Validity
Internal validity. The same author wrote the reader and the cross-checks, so independence is by method, not by person. The reader's factory-stamp rule was re-implemented from the documented rule of the second parser, so the two are not independent on that rule. The development-time counts come from AI-assisted development streams of the same pipeline, so a systematic misreading would repeat in both; AI assistance in the tooling is itself a source of correlated error that the independent counts only partly address. No error rate was measured for the second parser. The measurements were taken on the combined code before it was divided for release, not on the released code.
Construct validity. A row is a record the device printed, not proof of a user action. Times are reported as printed and converted only where the report prints its zone. The coverage gap counts sections, not evidence.
External validity. The sample is seven reports from four vendor families on Android 10, 15 and 16; three families have one report each. Android 11 to 14 and other vendors were not examined. All seven reports are in UTC+0, so zone and daylight-saving conversion are proven on constructed text only. The reports are a convenience sample obtained for work and tests, without random selection, and the content of a report depends on the state of the device at capture.
Conclusion validity. We make no statistical inference from seven reports; percentages describe the sample only.
Limitations. We made no benchmark against dumpstate-py, bugreport-extractor-library, MVT or other tools on the same reports, which is the most important missing measurement. We did not separate reading cost from output cost in the full 158-artifact run, did not measure memory beyond 2.2 million lines with the full profile or with many large reports held in the six-report cache, and ran no user study of whether examiners find the artifacts useful. The cause of the loss in the one failed altered-input variant is unknown.
Reproducibility. The synthetic fixtures are released with the code; the real reports cannot be released, so the real-data results can be checked only with comparable reports. A leak scan of the fixtures against the real reports found about 100 device-specific values, such as process identifiers, socket numbers and object hash codes, that had been copied into fixtures during construction; they were replaced with invented values. Two mainline-module version numbers in the base fixture of the first merged change (pull request #1795) were replaced only in a later one (#1809) and remain in the repository history. Fixture construction should therefore be followed by a leak scan run independently of whoever builds the fixtures.
8 Conclusion and Future Work
Android bug reports invite silent partial parsing: a misread line, a dump the platform cut short and a section no parser reads all look like missing data. A single-pass reader with a complete section index makes the second and third causes visible within the same pass, and testing on real and altered input exposes the first. On seven real reports the reader presented 158 artifacts in 20 to 55 s and at most 585 MB, agreed with independent counts, recorded the dumps the platform timed out, and showed that about 80 percent of the sections of two reports remain unread. The section index and the coverage gap need no second reading of the file, so any bug report parser, open-source tools included, can report them. What remains open is how the reader compares with other tools on the same reports, whether the results hold on Android 11 to 14 and other vendors, and which unread sections matter to examiners.
Future work, in order of value: (1) a comparison with dumpstate-py, bugreport-extractor-library and MVT on the same seven reports, with wall time, peak memory, sections reached and row agreement as metrics; (2) reports from Android 11 to 14 and from more vendors, including non-UTC zones; (3) a second, independently authored parser and an error rate for it; (4) an explanation of the failed altered-input variant; (5) a measurement of reading versus output cost for the full profile, and of memory on larger reports; (6) a study with examiners of which unread sections matter.
Artifact Availability
The reader and the 158 artifacts are released as part of ALEAPP [5] under the MIT licence, merged through seven pull requests: #1795, #1796, #1809, #1816, #1817, #1818 and #1819. The synthetic fixtures and test cases are released with the code, which passed the repository's lint checks. The measurements of Section 4.4 were taken before the code was divided into these pull requests. The real reports and the second parser are not released.
Data Handling Statement
Test data were of two kinds: (1) full file system extractions, sysdiagnose archives and Android bug reports of research devices (test devices) provided to the Lab by their owners and held in its research collection, used read-only for research with the owners' permission and never copied into any repository, fixture, paper or public file; (2) fully synthetic databases, property lists and bug report text written by the author with invented values (reserved example domains, documentation phone numbers, placeholder identifiers). The seven real bug reports in this paper are of kind (1), and only aggregate counts, device classes, operating system versions and section names are reported. No names, numbers, accounts, serial numbers, network names, package lists or file paths from the real data appear in this report. A leak scan compared every token and line of every released fixture against the real sources; the device-specific values it found were replaced with invented values (see Reproducibility), except that two module version numbers of the first merged change remain in the repository history. No offensive technique, exploit or credential-recovery method is described.
Declaration of AI Assistance
Parts of the tooling, the data checks and the drafting of this work were produced with AI assistance (Anthropic Claude), including the development streams described in Section 4.2. The author reviewed and ran the results and is responsible for the content.
References
- Android Open Source Project. [n. d.]. bugreport-format.md. platform/frameworks/native, cmds/dumpstate. Retrieved October 27, 2026 from https://android.googlesource.com/platform/frameworks/native/+/refs/heads/main/cmds/dumpstate/bugreport-format.md
- Android Open Source Project. [n. d.]. dumpstate.cpp. platform/frameworks/native, cmds/dumpstate. Retrieved October 27, 2026 from https://android.googlesource.com/platform/frameworks/native/+/refs/heads/main/cmds/dumpstate/dumpstate.cpp
- Android Open Source Project. [n. d.]. dumpsys.cpp. platform/frameworks/native, cmds/dumpsys. Retrieved October 27, 2026 from https://android.googlesource.com/platform/frameworks/native/+/refs/heads/main/cmds/dumpsys/dumpsys.cpp
- Android Open Source Project. [n. d.]. Read bug reports. Retrieved October 27, 2026 from https://source.android.com/docs/core/tests/debug/read-bug-reports
- Alexis Brignoni et al. [n. d.]. ALEAPP: Android Logs Events And Protobuf Parser. GitHub repository (MIT licence). Retrieved October 27, 2026 from https://github.com/abrignoni/ALEAPP
- CERT-EDF. [n. d.]. dumpstate-py: Extract useful structures from Android Bug Report. GitHub repository (Apache-2.0). Retrieved October 27, 2026 from https://github.com/CERT-EDF/dumpstate-py
- Simson L. Garfinkel. 2010. Digital forensics research: The next 10 years. Digital Investigation 7 (2010), S64–S73. https://doi.org/10.1016/j.diin.2010.05.009 (Bibliographic data confirmed from index records; full text not read.)
- Google. [n. d.]. Battery Historian. GitHub repository, archived December 29, 2022. Retrieved October 27, 2026 from https://github.com/google/battery-historian
- Google. [n. d.]. Capture and read bug reports. Android Developers. Retrieved October 27, 2026 from https://developer.android.com/studio/debug/bug-report
- Pinjia He, Jieming Zhu, Zibin Zheng, and Michael R. Lyu. 2017. Drain: An online log parsing approach with fixed depth tree. In Proceedings of the 2017 IEEE International Conference on Web Services (ICWS). IEEE, 33–40. https://doi.org/10.1109/ICWS.2017.13 (Bibliographic data confirmed from index records; full text not read.)
- Graeme Horsman. 2019. Tool testing and reliability issues in the field of digital forensics. Digital Investigation 28 (2019), 163–175. https://doi.org/10.1016/j.diin.2019.01.009 (Bibliographic data confirmed from index records; full text not read.)
- IsMyPhonePwned. [n. d.]. bugreport-extractor-library. GitHub repository (Apache-2.0). Retrieved October 27, 2026 from https://github.com/IsMyPhonePwned/bugreport-extractor-library
- MVT Project. [n. d.]. Android: Check a bug report with ADB. MVT documentation. Retrieved October 27, 2026 from https://docs.mvt.re/en/latest/android/adb/
- MVT Project. [n. d.]. Android methodology. MVT documentation. Retrieved October 27, 2026 from https://docs.mvt.re/en/latest/android/methodology/
- MVT Project. [n. d.]. Mobile Verification Toolkit (MVT). GitHub repository (Amnesty International Security Lab). Retrieved October 27, 2026 from https://github.com/mvt-project/mvt
- Jieming Zhu, Shilin He, Jinyang Liu, Pinjia He, Qi Xie, Zibin Zheng, and Michael R. Lyu. 2019. Tools and benchmarks for automated log parsing. In Proceedings of the 41st International Conference on Software Engineering: Software Engineering in Practice (ICSE-SEIP 2019). IEEE/ACM, 121–130. Preprint: arXiv:1811.03509