Skip to content

Commit 30ab36b

Browse files
committed
tp/ui: Add support for aflags
Trace Processor: - Added android_aflags table in android_tables.py. - Implemented parsing for AndroidAflags packets in AndroidProbesParser. - Added aflags.sql standard library module with android_aflags view. - Added diff tests in tests_aflags.py. UI: - Updated TraceInfoPage Android tab to display aflags data. - Added a new 'Android Aflags' section with a detailed grid. Test: diff_test_trace_processor.py --name-filter='AndroidAflags' Test: Manually verified UI with a trace containing aflags Change-Id: I1314b3017e23f94a66748b4e3e908c70beda715f
1 parent 87e2efe commit 30ab36b

File tree

14 files changed

+388
-7
lines changed

14 files changed

+388
-7
lines changed

Android.bp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16522,6 +16522,7 @@ filegroup {
1652216522
genrule {
1652316523
name: "perfetto_src_trace_processor_perfetto_sql_stdlib_stdlib",
1652416524
srcs: [
16525+
"src/trace_processor/perfetto_sql/stdlib/android/aflags.sql",
1652516526
"src/trace_processor/perfetto_sql/stdlib/android/anrs.sql",
1652616527
"src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql",
1652716528
"src/trace_processor/perfetto_sql/stdlib/android/auto/multiuser.sql",

BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3627,6 +3627,7 @@ perfetto_filegroup(
36273627
perfetto_filegroup(
36283628
name = "src_trace_processor_perfetto_sql_stdlib_android_android",
36293629
srcs = [
3630+
"src/trace_processor/perfetto_sql/stdlib/android/aflags.sql",
36303631
"src/trace_processor/perfetto_sql/stdlib/android/anrs.sql",
36313632
"src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql",
36323633
"src/trace_processor/perfetto_sql/stdlib/android/battery.sql",

src/trace_processor/importers/proto/android_probes_module.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ AndroidProbesModule::AndroidProbesModule(
6868
RegisterForField(TracePacket::kPowerRailsFieldNumber);
6969
RegisterForField(TracePacket::kAndroidEnergyEstimationBreakdownFieldNumber);
7070
RegisterForField(TracePacket::kEntityStateResidencyFieldNumber);
71+
RegisterForField(TracePacket::kAndroidAflagsFieldNumber);
7172
RegisterForField(TracePacket::kAndroidLogFieldNumber);
7273
RegisterForField(TracePacket::kPackagesListFieldNumber);
7374
RegisterForField(TracePacket::kUserListFieldNumber);
@@ -230,6 +231,9 @@ void AndroidProbesModule::ParseTracePacketData(
230231
const TracePacketData&,
231232
uint32_t field_id) {
232233
switch (field_id) {
234+
case TracePacket::kAndroidAflagsFieldNumber:
235+
parser_.ParseAndroidAflags(ts, decoder.android_aflags());
236+
return;
233237
case TracePacket::kAndroidLogFieldNumber:
234238
parser_.ParseAndroidLogPacket(ts, decoder.android_log());
235239
return;

src/trace_processor/importers/proto/android_probes_parser.cc

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "protos/perfetto/common/android_log_constants.pbzero.h"
4949
#include "protos/perfetto/common/builtin_clock.pbzero.h"
5050
#include "protos/perfetto/config/trace_config.pbzero.h"
51+
#include "protos/perfetto/trace/android/android_aflags.pbzero.h"
5152
#include "protos/perfetto/trace/android/android_game_intervention_list.pbzero.h"
5253
#include "protos/perfetto/trace/android/android_log.pbzero.h"
5354
#include "protos/perfetto/trace/android/android_system_property.pbzero.h"
@@ -151,7 +152,16 @@ AndroidProbesParser::AndroidProbesParser(TraceProcessorContext* context,
151152
power_rail_raw_name_id_(context->storage->InternString("raw_name")),
152153
power_rail_subsys_name_arg_id_(
153154
context->storage->InternString("subsystem_name")),
154-
rail_packet_timestamp_id_(context->storage->InternString("packet_ts")) {}
155+
rail_packet_timestamp_id_(context->storage->InternString("packet_ts")),
156+
aflags_read_only_id_(context->storage->InternString("read-only")),
157+
aflags_read_write_id_(context->storage->InternString("read-write")),
158+
aflags_default_id_(context->storage->InternString("default")),
159+
aflags_server_id_(context->storage->InternString("server")),
160+
aflags_local_id_(context->storage->InternString("local")),
161+
aflags_none_id_(context->storage->InternString("none")),
162+
aflags_aconfigd_id_(context->storage->InternString("aconfigd")),
163+
aflags_device_config_id_(context->storage->InternString("device_config")),
164+
aflags_unspecified_id_(context->storage->InternString("unspecified")) {}
155165

156166
void AndroidProbesParser::ParseRailDescriptor(
157167
const protos::pbzero::PowerRails_Decoder& evt) {
@@ -696,4 +706,67 @@ void AndroidProbesParser::ParseBtTraceEvent(int64_t ts, ConstBytes blob) {
696706
});
697707
}
698708

709+
StringId AndroidProbesParser::ToPermissionId(int32_t permission) {
710+
switch (permission) {
711+
case protos::pbzero::AndroidAflags::FLAG_PERMISSION_READ_ONLY:
712+
return aflags_read_only_id_;
713+
case protos::pbzero::AndroidAflags::FLAG_PERMISSION_READ_WRITE:
714+
return aflags_read_write_id_;
715+
case protos::pbzero::AndroidAflags::FLAG_PERMISSION_UNSPECIFIED:
716+
default:
717+
return aflags_unspecified_id_;
718+
}
719+
}
720+
721+
StringId AndroidProbesParser::ToValuePickedFromId(int32_t picked_from) {
722+
switch (picked_from) {
723+
case protos::pbzero::AndroidAflags::VALUE_PICKED_FROM_DEFAULT:
724+
return aflags_default_id_;
725+
case protos::pbzero::AndroidAflags::VALUE_PICKED_FROM_SERVER:
726+
return aflags_server_id_;
727+
case protos::pbzero::AndroidAflags::VALUE_PICKED_FROM_LOCAL:
728+
return aflags_local_id_;
729+
case protos::pbzero::AndroidAflags::VALUE_PICKED_FROM_UNSPECIFIED:
730+
default:
731+
return aflags_unspecified_id_;
732+
}
733+
}
734+
735+
StringId AndroidProbesParser::ToStorageBackendId(int32_t backend) {
736+
switch (backend) {
737+
case protos::pbzero::AndroidAflags::FLAG_STORAGE_BACKEND_NONE:
738+
return aflags_none_id_;
739+
case protos::pbzero::AndroidAflags::FLAG_STORAGE_BACKEND_ACONFIGD:
740+
return aflags_aconfigd_id_;
741+
case protos::pbzero::AndroidAflags::FLAG_STORAGE_BACKEND_DEVICE_CONFIG:
742+
return aflags_device_config_id_;
743+
case protos::pbzero::AndroidAflags::FLAG_STORAGE_BACKEND_UNSPECIFIED:
744+
default:
745+
return aflags_unspecified_id_;
746+
}
747+
}
748+
749+
void AndroidProbesParser::ParseAndroidAflags(int64_t ts, ConstBytes blob) {
750+
protos::pbzero::AndroidAflags::Decoder decoder(blob.data, blob.size);
751+
for (auto it = decoder.flags(); it; ++it) {
752+
protos::pbzero::AndroidAflags::Flag::Decoder flag(*it);
753+
754+
tables::AndroidAflagsTable::Row row;
755+
row.ts = ts;
756+
row.package = context_->storage->InternString(flag.package());
757+
row.name = context_->storage->InternString(flag.name());
758+
row.flag_namespace = context_->storage->InternString(flag.flag_namespace());
759+
row.container = context_->storage->InternString(flag.container());
760+
row.value = context_->storage->InternString(flag.value());
761+
if (flag.has_staged_value()) {
762+
row.staged_value = context_->storage->InternString(flag.staged_value());
763+
}
764+
row.permission = ToPermissionId(flag.permission());
765+
row.value_picked_from = ToValuePickedFromId(flag.value_picked_from());
766+
row.storage_backend = ToStorageBackendId(flag.storage_backend());
767+
768+
context_->storage->mutable_android_aflags_table()->Insert(row);
769+
}
770+
}
771+
699772
} // namespace perfetto::trace_processor

src/trace_processor/importers/proto/android_probes_parser.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "perfetto/protozero/field.h"
2323

24+
#include "protos/perfetto/trace/android/android_aflags.pbzero.h"
2425
#include "protos/perfetto/trace/power/power_rails.pbzero.h"
2526
#include "src/trace_processor/storage/trace_storage.h"
2627

@@ -49,11 +50,16 @@ class AndroidProbesParser {
4950
void ParseEntityStateResidency(int64_t ts, ConstBytes);
5051
void ParseInitialDisplayState(int64_t ts, ConstBytes);
5152
void ParseAndroidSystemProperty(int64_t ts, ConstBytes);
53+
void ParseAndroidAflags(int64_t ts, ConstBytes);
5254
void ParseBtTraceEvent(int64_t ts, ConstBytes);
5355

5456
private:
5557
void ParseAndroidLogEvent(int64_t ts, protozero::ConstBytes);
5658

59+
StringId ToPermissionId(int32_t);
60+
StringId ToValuePickedFromId(int32_t);
61+
StringId ToStorageBackendId(int32_t);
62+
5763
TraceProcessorContext* const context_;
5864
AndroidProbesTracker* const tracker_;
5965

@@ -75,6 +81,15 @@ class AndroidProbesParser {
7581
const StringId power_rail_raw_name_id_;
7682
const StringId power_rail_subsys_name_arg_id_;
7783
const StringId rail_packet_timestamp_id_;
84+
const StringId aflags_read_only_id_;
85+
const StringId aflags_read_write_id_;
86+
const StringId aflags_default_id_;
87+
const StringId aflags_server_id_;
88+
const StringId aflags_local_id_;
89+
const StringId aflags_none_id_;
90+
const StringId aflags_aconfigd_id_;
91+
const StringId aflags_device_config_id_;
92+
const StringId aflags_unspecified_id_;
7893
};
7994
} // namespace perfetto::trace_processor
8095

src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ perfetto_sql_source_set("android") {
3030
"winscope",
3131
]
3232
sources = [
33+
"aflags.sql",
3334
"anrs.sql",
3435
"app_process_starts.sql",
3536
"battery.sql",
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
--
2+
-- Copyright (C) 2026 The Android Open Source Project
3+
--
4+
-- Licensed under the Apache License, Version 2.0 (the "License");
5+
-- you may not use this file except in compliance with the License.
6+
-- You may obtain a copy of the License at
7+
--
8+
-- https://www.apache.org/licenses/LICENSE-2.0
9+
--
10+
-- Unless required by applicable law or agreed to in writing, software
11+
-- distributed under the License is distributed on an "AS IS" BASIS,
12+
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
-- See the License for the specific language governing permissions and
14+
-- limitations under the License.
15+
--
16+
17+
-- Android aconfig flags ("aflags") are a configuration system used to manage
18+
-- feature rollout and behavior across the Android platform.
19+
--
20+
-- For more details on aconfig, see:
21+
-- https://source.android.com/docs/setup/build/feature-flagging/declare-flag
22+
--
23+
-- This view presents snapshots of the state of these flags as captured
24+
-- during the trace. Data is collected by the `android.aflags` data-source,
25+
-- which periodically polls the `aflags` tool on Android devices.
26+
-- Each row in this view represents the state of a single flag at a specific
27+
-- point in time (the `ts` column).
28+
CREATE PERFETTO VIEW android_aflags (
29+
-- Timestamp of the flag snapshot.
30+
ts TIMESTAMP,
31+
-- Package name of the flag (e.g. "com.android.window.flags").
32+
package STRING,
33+
-- Name of the flag within the package (e.g. "enable_multi_window").
34+
name STRING,
35+
-- The namespace this flag belongs to (often used for grouping).
36+
flag_namespace STRING,
37+
-- The container for the flag (e.g. "system", "product").
38+
container STRING,
39+
-- Current effective value of the flag at this timestamp.
40+
value STRING,
41+
-- The value this flag will take after the next reboot, if a change has
42+
-- been staged.
43+
staged_value STRING,
44+
-- Whether the flag is read-only or read-write.
45+
permission STRING,
46+
-- Where the current value was picked from (e.g. "default", "local", "server").
47+
value_picked_from STRING,
48+
-- The underlying storage backend for this flag (e.g. "aconfigd", "device_config").
49+
storage_backend STRING
50+
) AS
51+
SELECT
52+
ts,
53+
package,
54+
name,
55+
flag_namespace,
56+
container,
57+
value,
58+
staged_value,
59+
permission,
60+
value_picked_from,
61+
storage_backend
62+
FROM __intrinsic_android_aflags;

src/trace_processor/storage/trace_storage.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,13 @@ class TraceStorage {
413413
const SqlStats& sql_stats() const { return sql_stats_; }
414414
SqlStats* mutable_sql_stats() { return &sql_stats_; }
415415

416+
const tables::AndroidAflagsTable& android_aflags_table() const {
417+
return table<tables::AndroidAflagsTable>();
418+
}
419+
tables::AndroidAflagsTable* mutable_android_aflags_table() {
420+
return mutable_table<tables::AndroidAflagsTable>();
421+
}
422+
416423
const tables::AndroidCpuPerUidTrackTable& android_cpu_per_uid_track_table()
417424
const {
418425
return table<tables::AndroidCpuPerUidTrackTable>();

src/trace_processor/tables/android_tables.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,46 @@
359359
'android_user_id': '''User id on device''',
360360
}))
361361

362+
ANDROID_AFLAGS_TABLE = Table(
363+
python_module=__file__,
364+
class_name='AndroidAflagsTable',
365+
sql_name='__intrinsic_android_aflags',
366+
columns=[
367+
C('ts', CppInt64()),
368+
C('package', CppString()),
369+
C('name', CppString()),
370+
C('flag_namespace', CppString()),
371+
C('container', CppString()),
372+
C('value', CppString()),
373+
C('staged_value', CppOptional(CppString())),
374+
C('permission', CppString()),
375+
C('value_picked_from', CppString()),
376+
C('storage_backend', CppString()),
377+
],
378+
tabledoc=TableDoc(
379+
doc='''
380+
A table presenting all aconfig flags and their values.
381+
This is generated by the android.aflags data-source.
382+
''',
383+
group='Android',
384+
columns={
385+
'ts': 'Timestamp of the flag snapshot.',
386+
'package': 'Package of the flag.',
387+
'name': 'Name of the flag.',
388+
'flag_namespace': 'Namespace of the flag.',
389+
'container': 'Container of the flag.',
390+
'value': 'Current value of the flag.',
391+
'staged_value': 'Value of the flag after next reboot.',
392+
'permission': 'Permission of the flag (read-only or read-write).',
393+
'value_picked_from': 'Source of the current flag value.',
394+
'storage_backend': 'The storage backend that owns this flag.',
395+
},
396+
),
397+
)
398+
362399
# Keep this list sorted.
363400
ALL_TABLES = [
401+
ANDROID_AFLAGS_TABLE,
364402
ANDROID_CPU_PER_UID_TRACK_TABLE,
365403
ANDROID_DUMPSTATE_TABLE,
366404
ANDROID_GAME_INTERVENTION_LIST_TABLE,

src/trace_processor/trace_processor_impl.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,7 @@ std::vector<PerfettoSqlEngine::StaticTable> TraceProcessorImpl::GetStaticTables(
10481048
std::vector<PerfettoSqlEngine::StaticTable> tables;
10491049
AddStaticTable(tables, storage->mutable_aggregate_profile_table());
10501050
AddStaticTable(tables, storage->mutable_aggregate_sample_table());
1051+
AddStaticTable(tables, storage->mutable_android_aflags_table());
10511052
AddStaticTable(tables, storage->mutable_android_cpu_per_uid_track_table());
10521053
AddStaticTable(tables, storage->mutable_android_dumpstate_table());
10531054
AddStaticTable(tables,

0 commit comments

Comments
 (0)