xref: /aosp_15_r20/external/perfetto/tools/update-statsd-descriptor (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Workerimport os
17*6dbdd20aSAndroid Build Coastguard Workerimport sys
18*6dbdd20aSAndroid Build Coastguard Workerimport re
19*6dbdd20aSAndroid Build Coastguard Workerimport subprocess
20*6dbdd20aSAndroid Build Coastguard Workerimport pathlib
21*6dbdd20aSAndroid Build Coastguard Workerimport tempfile
22*6dbdd20aSAndroid Build Coastguard Workerimport contextlib
23*6dbdd20aSAndroid Build Coastguard Workerimport argparse
24*6dbdd20aSAndroid Build Coastguard Workerimport itertools
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard WorkerROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
27*6dbdd20aSAndroid Build Coastguard WorkerTOOLS_DIR = os.path.join(ROOT_DIR, "tools")
28*6dbdd20aSAndroid Build Coastguard WorkerOUT_DIR = os.path.join(ROOT_DIR, "out", "tools")
29*6dbdd20aSAndroid Build Coastguard WorkerNINJA = os.path.join(TOOLS_DIR, "ninja")
30*6dbdd20aSAndroid Build Coastguard WorkerGN = os.path.join(TOOLS_DIR, "gn")
31*6dbdd20aSAndroid Build Coastguard WorkerPROTOC_PATH = os.path.join(OUT_DIR, "protoc")
32*6dbdd20aSAndroid Build Coastguard WorkerDESCRIPTOR_PATH = os.path.join(ROOT_DIR, "src", "trace_processor", "importers",
33*6dbdd20aSAndroid Build Coastguard Worker                               "proto", "atoms.descriptor")
34*6dbdd20aSAndroid Build Coastguard WorkerPROTOBUF_BUILTINS_DIR = os.path.join(ROOT_DIR, "buildtools", "protobuf", "src")
35*6dbdd20aSAndroid Build Coastguard WorkerPROTO_LOGGING_URL = "https://android.googlesource.com/platform/frameworks/proto_logging.git"
36*6dbdd20aSAndroid Build Coastguard WorkerATOM_RE = r"  message_type {\n.   name: \"Atom\"(\n    .+)+(\n  })"
37*6dbdd20aSAndroid Build Coastguard WorkerFIELD_RE = r"    field {\n      name: \"([^\"]+)\"\n      number: ([0-9]+)"
38*6dbdd20aSAndroid Build Coastguard WorkerEXTENSIONS_RE = r" extension {\n    name: \"([^\"]+)\"\n    extendee: \".android.os.statsd.Atom\"\n    number: ([0-9]+)(\n    .+)+(\n  })"
39*6dbdd20aSAndroid Build Coastguard WorkerATOM_IDS_PATH = os.path.join(ROOT_DIR, "protos", "perfetto", "config", "statsd",
40*6dbdd20aSAndroid Build Coastguard Worker                             "atom_ids.proto")
41*6dbdd20aSAndroid Build Coastguard Worker
42*6dbdd20aSAndroid Build Coastguard WorkerATOM_IDS_TEMPLATE = """/*
43*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
44*6dbdd20aSAndroid Build Coastguard Worker *
45*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
46*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
47*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
48*6dbdd20aSAndroid Build Coastguard Worker *
49*6dbdd20aSAndroid Build Coastguard Worker *      http://www.apache.org/licenses/LICENSE-2.0
50*6dbdd20aSAndroid Build Coastguard Worker *
51*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
52*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
53*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
54*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
55*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
56*6dbdd20aSAndroid Build Coastguard Worker */
57*6dbdd20aSAndroid Build Coastguard Workersyntax = "proto2";
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard Workerpackage perfetto.protos;
60*6dbdd20aSAndroid Build Coastguard Worker
61*6dbdd20aSAndroid Build Coastguard Worker// This enum is obtained by post-processing
62*6dbdd20aSAndroid Build Coastguard Worker// AOSP/frameworks/proto_logging/stats/atoms.proto through
63*6dbdd20aSAndroid Build Coastguard Worker// AOSP/external/perfetto/tools/update-statsd-descriptor, which extracts one
64*6dbdd20aSAndroid Build Coastguard Worker// enum value for each proto field defined in the upstream atoms.proto.
65*6dbdd20aSAndroid Build Coastguard Workerenum AtomId {{
66*6dbdd20aSAndroid Build Coastguard Worker  ATOM_UNSPECIFIED = 0;
67*6dbdd20aSAndroid Build Coastguard Worker{atoms}
68*6dbdd20aSAndroid Build Coastguard Worker}}"""
69*6dbdd20aSAndroid Build Coastguard Worker
70*6dbdd20aSAndroid Build Coastguard Worker
71*6dbdd20aSAndroid Build Coastguard Workerdef call(*cmd, stdin=None):
72*6dbdd20aSAndroid Build Coastguard Worker  try:
73*6dbdd20aSAndroid Build Coastguard Worker    return subprocess.check_output(cmd, stdin=stdin)
74*6dbdd20aSAndroid Build Coastguard Worker  except subprocess.CalledProcessError as e:
75*6dbdd20aSAndroid Build Coastguard Worker    print("Error running the command:")
76*6dbdd20aSAndroid Build Coastguard Worker    print(" ".join(cmd))
77*6dbdd20aSAndroid Build Coastguard Worker    print(e)
78*6dbdd20aSAndroid Build Coastguard Worker    exit(1)
79*6dbdd20aSAndroid Build Coastguard Worker
80*6dbdd20aSAndroid Build Coastguard Worker
81*6dbdd20aSAndroid Build Coastguard Worker# Extract core atoms. To do this we regex the pbtext
82*6dbdd20aSAndroid Build Coastguard Worker# of the descriptor. This is hopefully:
83*6dbdd20aSAndroid Build Coastguard Worker# - more stable than regexing atom.proto directly
84*6dbdd20aSAndroid Build Coastguard Worker# - less complicated than parsing finding, importing, and using the
85*6dbdd20aSAndroid Build Coastguard Worker#   Python protobuf library.
86*6dbdd20aSAndroid Build Coastguard Workerdef atoms_from_descriptor():
87*6dbdd20aSAndroid Build Coastguard Worker  with contextlib.ExitStack() as stack:
88*6dbdd20aSAndroid Build Coastguard Worker    descriptor_in = stack.enter_context(open(DESCRIPTOR_PATH))
89*6dbdd20aSAndroid Build Coastguard Worker    pbtext = call(
90*6dbdd20aSAndroid Build Coastguard Worker        PROTOC_PATH,
91*6dbdd20aSAndroid Build Coastguard Worker        f"--proto_path={PROTOBUF_BUILTINS_DIR}",
92*6dbdd20aSAndroid Build Coastguard Worker        f"{PROTOBUF_BUILTINS_DIR}/google/protobuf/descriptor.proto",
93*6dbdd20aSAndroid Build Coastguard Worker        "--decode=google.protobuf.FileDescriptorSet",
94*6dbdd20aSAndroid Build Coastguard Worker        stdin=descriptor_in).decode("utf8")
95*6dbdd20aSAndroid Build Coastguard Worker
96*6dbdd20aSAndroid Build Coastguard Worker    # Core atoms:
97*6dbdd20aSAndroid Build Coastguard Worker    atom_pbtext = re.search(ATOM_RE, pbtext, re.MULTILINE)[0]
98*6dbdd20aSAndroid Build Coastguard Worker    for m in re.finditer(FIELD_RE, atom_pbtext):
99*6dbdd20aSAndroid Build Coastguard Worker      yield m[1], m[2]
100*6dbdd20aSAndroid Build Coastguard Worker
101*6dbdd20aSAndroid Build Coastguard Worker    # Extensions
102*6dbdd20aSAndroid Build Coastguard Worker    for m in re.finditer(EXTENSIONS_RE, pbtext):
103*6dbdd20aSAndroid Build Coastguard Worker      yield m[1], m[2]
104*6dbdd20aSAndroid Build Coastguard Worker
105*6dbdd20aSAndroid Build Coastguard Worker
106*6dbdd20aSAndroid Build Coastguard Workerdef main():
107*6dbdd20aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
108*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument("--atoms-checkout")
109*6dbdd20aSAndroid Build Coastguard Worker  args = parser.parse_args()
110*6dbdd20aSAndroid Build Coastguard Worker
111*6dbdd20aSAndroid Build Coastguard Worker  call(GN, "gen", OUT_DIR, "--args=is_debug=false")
112*6dbdd20aSAndroid Build Coastguard Worker  call(NINJA, "-C", OUT_DIR, "protoc")
113*6dbdd20aSAndroid Build Coastguard Worker
114*6dbdd20aSAndroid Build Coastguard Worker  with contextlib.ExitStack() as stack:
115*6dbdd20aSAndroid Build Coastguard Worker
116*6dbdd20aSAndroid Build Coastguard Worker    # Write the descriptor.
117*6dbdd20aSAndroid Build Coastguard Worker    if args.atoms_checkout:
118*6dbdd20aSAndroid Build Coastguard Worker      atoms_root = args.atoms_checkout
119*6dbdd20aSAndroid Build Coastguard Worker      proto_logging_dir = os.path.join(atoms_root, "frameworks",
120*6dbdd20aSAndroid Build Coastguard Worker                                       "proto_logging")
121*6dbdd20aSAndroid Build Coastguard Worker    else:
122*6dbdd20aSAndroid Build Coastguard Worker      atoms_root = stack.enter_context(tempfile.TemporaryDirectory())
123*6dbdd20aSAndroid Build Coastguard Worker      proto_logging_dir = os.path.join(atoms_root, "frameworks",
124*6dbdd20aSAndroid Build Coastguard Worker                                       "proto_logging")
125*6dbdd20aSAndroid Build Coastguard Worker      pathlib.Path(proto_logging_dir).mkdir(parents=True, exist_ok=True)
126*6dbdd20aSAndroid Build Coastguard Worker      call("git", "clone", PROTO_LOGGING_URL, proto_logging_dir)
127*6dbdd20aSAndroid Build Coastguard Worker
128*6dbdd20aSAndroid Build Coastguard Worker
129*6dbdd20aSAndroid Build Coastguard Worker    extensions_path = os.path.join(proto_logging_dir, "stats", "atoms")
130*6dbdd20aSAndroid Build Coastguard Worker    extensions = []
131*6dbdd20aSAndroid Build Coastguard Worker    if os.path.isdir(extensions_path):
132*6dbdd20aSAndroid Build Coastguard Worker      for dirpath, dirnames, filenames in os.walk(extensions_path):
133*6dbdd20aSAndroid Build Coastguard Worker        for name in filenames:
134*6dbdd20aSAndroid Build Coastguard Worker          if name.endswith(".proto"):
135*6dbdd20aSAndroid Build Coastguard Worker            path = os.path.join(dirpath, name)
136*6dbdd20aSAndroid Build Coastguard Worker            extensions.append(path)
137*6dbdd20aSAndroid Build Coastguard Worker
138*6dbdd20aSAndroid Build Coastguard Worker    cmd = [
139*6dbdd20aSAndroid Build Coastguard Worker      f"--proto_path={PROTOBUF_BUILTINS_DIR}",
140*6dbdd20aSAndroid Build Coastguard Worker      f"--proto_path={atoms_root}",
141*6dbdd20aSAndroid Build Coastguard Worker      f"--descriptor_set_out={DESCRIPTOR_PATH}",
142*6dbdd20aSAndroid Build Coastguard Worker      "--include_imports",
143*6dbdd20aSAndroid Build Coastguard Worker      ] + extensions + [
144*6dbdd20aSAndroid Build Coastguard Worker      os.path.join(proto_logging_dir, "stats", "atoms.proto")
145*6dbdd20aSAndroid Build Coastguard Worker    ]
146*6dbdd20aSAndroid Build Coastguard Worker    call(PROTOC_PATH, *cmd)
147*6dbdd20aSAndroid Build Coastguard Worker
148*6dbdd20aSAndroid Build Coastguard Worker    lines = []
149*6dbdd20aSAndroid Build Coastguard Worker    for name, field in atoms_from_descriptor():
150*6dbdd20aSAndroid Build Coastguard Worker      name = "ATOM_" + name.upper()
151*6dbdd20aSAndroid Build Coastguard Worker      lines.append(f"  {name} = {field};".format(name=name, field=field))
152*6dbdd20aSAndroid Build Coastguard Worker    atom_ids_out = stack.enter_context(open(ATOM_IDS_PATH, "w"))
153*6dbdd20aSAndroid Build Coastguard Worker    atom_ids_out.write(ATOM_IDS_TEMPLATE.format(atoms="\n".join(lines)))
154*6dbdd20aSAndroid Build Coastguard Worker
155*6dbdd20aSAndroid Build Coastguard Worker
156*6dbdd20aSAndroid Build Coastguard Workerif __name__ == "__main__":
157*6dbdd20aSAndroid Build Coastguard Worker  sys.exit(main())
158