• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2# Copyright (C) 2025 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#      http://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
17import argparse
18from .command import Command
19from .validation_error import ValidationError
20
21TRACED_ENABLE_PROP = "persist.traced.enable"
22TRACED_RELAY_PRODUCER_PORT_PROP = "traced.relay_producer_port"
23TRACED_RELAY_PORT_PROP = "traced_relay.relay_port"
24TRACED_HYPERVISOR_PROP = "ro.traced.hypervisor"
25
26def add_vm_parser(subparsers):
27  vm_parser = subparsers.add_parser('vm',
28                                      help=('The vm subcommand is used '
29                                            'to configure perfetto in '
30                                            'virtualized Android.'))
31  vm_subparsers = vm_parser.add_subparsers(dest='vm_subcommand')
32
33  # Traced relay subcommand
34  traced_relay_parser = vm_subparsers.add_parser('traced-relay',
35                                                  help=('Configure traced_relay'))
36  traced_relay_subparsers = traced_relay_parser.add_subparsers(dest='vm_traced_relay_subcommand')
37
38  enable_tr_parser = traced_relay_subparsers.add_parser('enable', help=('Enable traced_relay'))
39  enable_tr_parser.add_argument('relay_port', help='Socket address to communicate with traced.')
40
41  traced_relay_subparsers.add_parser('disable', help=('Disable traced_relay'))
42
43  # Traced relay producer subcommand
44  relay_producer_parser = vm_subparsers.add_parser('relay-producer',
45                                                  help=('Configure traced\'s relay '
46                                                        'producer socket'))
47  relay_producer_subparsers = \
48        relay_producer_parser.add_subparsers(dest='vm_relay_producer_subcommand')
49
50  enable_rp_parser = \
51        relay_producer_subparsers.add_parser('enable',
52                                             help=('Enable traced\'s relay producer port'))
53  enable_rp_parser.add_argument('--address', dest='relay_prod_port',
54                                default='vsock://-1:30001',
55                                help='Socket address used for relayed communication.')
56
57  relay_producer_subparsers.add_parser('disable', help=('Disable traced\'s relay producer port'))
58
59
60def create_vm_command(args):
61  if args.vm_subcommand == 'traced-relay':
62    relay_port = None
63    if args.vm_traced_relay_subcommand == 'enable':
64      relay_port = args.relay_port
65
66    return VmCommand(args.vm_subcommand,
67                     args.vm_traced_relay_subcommand,
68                     relay_port, None)
69  # relay-producer command
70  relay_prod_port = None
71  if args.vm_relay_producer_subcommand == 'enable':
72    relay_prod_port = args.relay_prod_port
73  return VmCommand(args.vm_subcommand,
74                   args.vm_relay_producer_subcommand,
75                   None, relay_prod_port)
76
77class VmCommand(Command):
78  """
79  Represents commands which configure perfetto
80  in virtualized Android.
81  """
82  def __init__(self, type, subcommand, relay_port, relay_prod_port):
83    super().__init__(type)
84    self.subcommand = subcommand
85    self.relay_port = relay_port
86    self.relay_prod_port = relay_prod_port
87
88  def validate(self, device):
89    raise NotImplementedError
90
91  def execute(self, device):
92    error = device.check_device_connection()
93    if error is not None:
94      return error
95    device.root_device()
96    if self.type == 'traced-relay':
97      return self.traced_relay_execute(device)
98    # else it's a relay-producer command
99    return self.relay_producer_execute(device)
100
101  def traced_relay_execute(self, device):
102    if self.subcommand == 'enable':
103      if (len(device.get_prop(TRACED_HYPERVISOR_PROP)) == 0):
104        # Traced_relay can only be used in virtualized environments,
105        # therefore set the |TRACED_HYPERVISOR_PROP| to true if
106        # enabling traced_relay.
107        print(f"Setting sysprop \"{TRACED_HYPERVISOR_PROP}\" to \"true\"")
108        device.set_prop(TRACED_HYPERVISOR_PROP, "true")
109      device.set_prop(TRACED_RELAY_PORT_PROP, self.relay_port)
110      device.set_prop(TRACED_ENABLE_PROP, "2")
111    else: # disable
112      device.set_prop(TRACED_ENABLE_PROP, "1")
113    return None
114
115  def relay_producer_execute(self, device):
116    if self.subcommand == 'enable':
117      device.set_prop(TRACED_ENABLE_PROP, "0")
118      device.set_prop(TRACED_RELAY_PRODUCER_PORT_PROP, self.relay_prod_port)
119      device.set_prop(TRACED_ENABLE_PROP, "1")
120    else: #disable
121      device.set_prop(TRACED_ENABLE_PROP, "0")
122      device.clear_prop(TRACED_RELAY_PRODUCER_PORT_PROP)
123      device.set_prop(TRACED_ENABLE_PROP, "1")
124    return None
125