From 858496e60bba1d66016b243b00cb8c7c1a0c1119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donncha=20=C3=93=20Cearbhaill?= Date: Sat, 5 Sep 2026 16:17:43 +0200 Subject: [PATCH] End a settings record at a blank line dumpsys prints a blank line after every namespace block and after a change history, and the generation registry and any vendor dumps follow the last block before the section trailer. A record ran until the next `_id:` line, heading or trailer, so the last row of the section absorbed those dumps into whichever field came last. A blank line now closes the record being read; lines that follow it without an `_id:` are skipped until the next row or heading. The fixture carries a generation registry after its last block, modelled on the AOSP dump, and the last row is pinned to exactly its own fields. --- src/mvt/android/artifacts/settings.py | 8 ++++++++ tests/android/test_artifact_settings.py | 14 ++++++++++++++ .../artifacts/android_data/bugreport/dumpstate.txt | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/src/mvt/android/artifacts/settings.py b/src/mvt/android/artifacts/settings.py index 627fafe3..39257c06 100644 --- a/src/mvt/android/artifacts/settings.py +++ b/src/mvt/android/artifacts/settings.py @@ -177,6 +177,14 @@ class Settings(AndroidArtifact): if namespace is None: continue + if not line.strip(): + # dumpsys prints a blank line after every namespace block and + # after a change history, and other dumps such as the + # generation registry follow the last block, so a blank line + # closes the record being read. + flush() + continue + if line.startswith("_id:"): flush() record_lines = [line] diff --git a/tests/android/test_artifact_settings.py b/tests/android/test_artifact_settings.py index c3fde0d2..2192c12b 100644 --- a/tests/android/test_artifact_settings.py +++ b/tests/android/test_artifact_settings.py @@ -87,6 +87,20 @@ class TestSettingsArtifact: assert record["value"] == "1" assert record["isValuePreservedInRestore"] == "false" + def test_dumps_after_the_last_block_are_not_part_of_the_last_row(self): + settings = parse_bugreport_settings() + + assert settings.results[-1] == { + "namespace": "secure", + "user": "10", + "_id": "311", + "name": "accessibility_enabled", + "pkg": "android", + "value": "0", + "tag": "null", + "history": [], + } + def test_repeated_names_are_kept_as_separate_records(self): settings = parse_bugreport_settings() diff --git a/tests/artifacts/android_data/bugreport/dumpstate.txt b/tests/artifacts/android_data/bugreport/dumpstate.txt index 56a5d864..4dffc585 100644 --- a/tests/artifacts/android_data/bugreport/dumpstate.txt +++ b/tests/artifacts/android_data/bugreport/dumpstate.txt @@ -308,4 +308,9 @@ _id:240 name:accessibility_enabled pkg:android value:1 default:0 defaultSystemSe SECURE SETTINGS (user 10) _id:311 name:accessibility_enabled pkg:android value:0 tag:null +GENERATION REGISTRY +Maximum number of backing stores:8 +Number of backing stores:1 +_Backing store for type:SETTINGS_SECURE user:10 size:1024 cachedEntries:1 + --------- 0.019s was the duration of dumpsys settings, ending at: 2022-03-29 23:14:28