1/* 2 * Copyright 2021 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 */ 16syntax = "proto3"; 17package layoutinspector.compose.inspection; 18option java_package = "layoutinspector.compose.inspection"; 19option java_outer_classname = "LayoutInspectorComposeProtocol"; 20 21// ======= MESSAGES ======= 22 23// A mapping of |string| to |int32|, so strings can be efficiently reused across nodes 24// Any time a text value in any of these messages has an |int32| type, it means it will do a 25// lookup in a string table on the client. 26message StringEntry { 27 int32 id = 1; 28 string str = 2; 29} 30 31message Point { 32 int32 x = 1; 33 int32 y = 2; 34} 35 36message Rect { 37 int32 x = 1; 38 int32 y = 2; 39 int32 w = 3; 40 int32 h = 4; 41} 42 43// A Quad holds the 4 corners of a polygon in drawing order, that represent the transformed shape 44// of a Rect after applying some affine or perspective transformations. 45message Quad { 46 sint32 x0 = 1; 47 sint32 y0 = 2; 48 sint32 x1 = 3; 49 sint32 y1 = 4; 50 sint32 x2 = 5; 51 sint32 y2 = 6; 52 sint32 x3 = 7; 53 sint32 y3 = 8; 54} 55 56message Bounds { 57 // The bounds of some element in the layout tree 58 Rect layout = 1; 59 // Bounds transformed in preparation for final rendering 60 Quad render = 2; 61} 62 63message ComposableRoot { 64 // The ID of the View this Composable tree is rooted underneath 65 int64 view_id = 1; 66 // All composables owned by this view (usually just one but could be more) 67 repeated ComposableNode nodes = 2; 68 // All views owned by this view that should be hidden 69 repeated int64 views_to_skip = 3; 70} 71 72message ComposableNode { 73 sint64 id = 1; 74 repeated ComposableNode children = 2; 75 76 // The hash of the file's package, for disambiguating same filenames in different folders 77 int32 package_hash = 3; 78 int32 filename = 4; // The file this Composable is defined in 79 int32 line_number = 5; // The line number within the file 80 int32 offset = 6; // Offset into the file for the exact character position 81 82 int32 name = 7; 83 84 Bounds bounds = 8; 85 86 enum Flags { 87 NONE = 0; 88 SYSTEM_CREATED = 0x1; 89 HAS_MERGED_SEMANTICS = 0x2; 90 HAS_UNMERGED_SEMANTICS = 0x4; 91 INLINED = 0x8; 92 // If a node has the NESTED_SINGLE_CHILDREN flag, it means the children should be 93 // interpreted as a subtree of single nodes. 94 NESTED_SINGLE_CHILDREN = 0x10; 95 } 96 int32 flags = 9; 97 98 int64 view_id = 10; 99 100 // The number of recompositions detected since the last counter reset 101 int32 recompose_count = 11; 102 103 // The number of recomposition skips detected since the last counter reset 104 int32 recompose_skips = 12; 105 106 // The unique id of an anchor. This used to be its hashcode. See InspectorNode.anchorId. 107 sint32 anchor_hash = 13; 108} 109 110// In Android, a resource id is a simple integer. This class holds the namespace, type, and name 111// of such a resource id. 112// For example, with "@android:id/textView": 113// type: id 114// namespace: android 115// name: textView 116message Resource { 117 int32 type = 1; 118 int32 namespace = 2; 119 int32 name = 3; 120} 121 122// Data that helps us identify a lambda block in code 123message LambdaValue { 124 int32 package_name = 1; // the package part of the containing class name 125 int32 file_name = 2; // the file name of the containing class 126 int32 lambda_name = 3; // the name of the lambda class 127 int32 function_name = 4; // the function name if this is a function reference 128 int32 start_line_number = 5; // the line number of the start of the lambda 129 int32 end_line_number = 6; // the line number of the end of the lambda 130} 131 132// Parameters to a @Composable function 133message Parameter { 134 enum Type { 135 UNSPECIFIED = 0; 136 STRING = 1; 137 BOOLEAN = 2; 138 DOUBLE = 3; 139 FLOAT = 4; 140 INT32 = 5; 141 INT64 = 6; 142 COLOR = 7; 143 RESOURCE = 8; 144 DIMENSION_DP = 9; 145 DIMENSION_SP = 10; 146 DIMENSION_EM = 11; 147 LAMBDA = 12; 148 FUNCTION_REFERENCE = 13; 149 ITERABLE = 14; 150 } 151 152 Type type = 1; 153 int32 name = 2; 154 repeated Parameter elements = 3; 155 ParameterReference reference = 4; 156 157 // For elements inside another Parameter instance, this index refer to the 158 // "natural" index of the parent composite value in the agent. 159 // 160 // We record this to be able to identify a reference to another parameter in 161 // the client and agent. Note that e.g: 162 // - null elements in a List are omitted 163 // A reference will indicate the index among all values, such that we don't 164 // have to count nulls during a GetParameterDetailsCommand. 165 sint32 index = 5; 166 167 oneof value { 168 int32 int32_value = 11; 169 int64 int64_value = 12; 170 double double_value = 13; 171 float float_value = 14; 172 Resource resource_value = 15; 173 LambdaValue lambda_value = 16; 174 } 175} 176 177// A reference to a "part" of a parameter value 178message ParameterReference { 179 enum Kind { 180 UNSPECIFIED = 0; 181 NORMAL = 1; 182 MERGED_SEMANTICS = 2; 183 UNMERGED_SEMANTICS = 3; 184 } 185 186 sint64 composable_id = 1; 187 188 // Identifies an index into a ParameterGroup 189 int32 parameter_index = 2; 190 191 // If the parameter value is a composite value such as: 192 // List<MyClass> 193 // then: 194 // composite_index[0] is the index into the List 195 // composite_index[1] is the index into the fields in MyClass 196 // composite_index[2] is the index into the field found by [1] etc... 197 repeated int32 composite_index = 3; 198 199 // The kind of parameter this is a reference to 200 Kind kind = 4; 201 202 // The anchor hash of the composable. See InspectorNode.anchorId. 203 sint32 anchor_hash = 5; 204} 205 206// A collection of all parameters associated with a single composable 207message ParameterGroup { 208 sint64 composable_id = 1; 209 repeated Parameter parameter = 3; 210 repeated Parameter merged_semantics = 4; 211 repeated Parameter unmerged_semantics = 5; 212} 213 214// ======= COMMANDS, RESPONSES, AND EVENTS ======= 215 216// Response fired when incoming command bytes cannot be parsed or handled. This may occur if a newer 217// version of the client tries to interact with an older inspector. 218message UnknownCommandResponse { 219 // The initial command bytes received that couldn't be handled. By returning this back to the 220 // client, it should be able to identify what they sent that failed on the inspector side. 221 bytes command_bytes = 1; 222} 223 224// Request all composables found under a layout tree rooted under the specified view 225message GetComposablesCommand { 226 int64 root_view_id = 1; 227 // If true, only show composable nodes created by the user's own app 228 bool skip_system_composables = 2; 229 // If the cached data generation matches the specified generation then the cache is still valid. 230 int32 generation = 3; 231 // If true, extract all parameters even if `delayParameterExtractions` is off. 232 bool extract_all_parameters = 4; 233} 234 235message GetComposablesResponse { 236 // A collection of all text referenced by other fields in this message 237 repeated StringEntry strings = 1; 238 repeated ComposableRoot roots = 2; 239} 240 241message GetParametersCommand { 242 int64 root_view_id = 1; // Used for filtering out composables from unrelated layout trees 243 sint64 composable_id = 2; 244 // As an optimization, we can skip over searching system composables if we know we don't care 245 // about them. 246 bool skip_system_composables = 3; 247 // Max number of recursions into nested composite parameter values. 248 // It is possible to dig in further by using: GetParameterDetailsCommand. 249 // If not specified the default is 2. 250 int32 max_recursions = 4; 251 // Max number of initial elements in an iterable such as a List/Array. 252 // It is possible to request more elements by using: GetParameterDetailsCommand. 253 // If not specified the default is 5. 254 int32 max_initial_iterable_size = 5; 255 // If the cached data generation matches the specified generation then the cache is still valid. 256 int32 generation = 6; 257 // The anchor hash of the composable. See InspectorNode.anchorId. 258 sint32 anchor_hash = 7; 259} 260 261message GetParametersResponse { 262 // A collection of all text referenced by other fields in this message 263 repeated StringEntry strings = 1; 264 ParameterGroup parameter_group = 2; 265} 266 267// Request all parameters for all composables under a particular layout tree 268message GetAllParametersCommand { 269 int64 root_view_id = 1; 270 bool skip_system_composables = 2; 271 int32 max_recursions = 3; 272 int32 max_initial_iterable_size = 4; 273 // If the cached data generation matches the specified generation then the cache is still valid. 274 int32 generation = 5; 275} 276 277message GetAllParametersResponse { 278 int64 root_view_id = 1; // Echoed from GetAllParametersCommand 279 repeated StringEntry strings = 2; 280 repeated ParameterGroup parameter_groups = 3; 281} 282 283// Request parameter details for the parameter specified 284message GetParameterDetailsCommand { 285 int64 root_view_id = 1; 286 ParameterReference reference = 2; 287 int32 start_index = 3; 288 int32 max_elements = 4; 289 bool skip_system_composables = 5; 290 int32 max_recursions = 6; 291 int32 max_initial_iterable_size = 7; 292 // If the cached data generation matches the specified generation then the cache is still valid. 293 int32 generation = 8; 294} 295 296message GetParameterDetailsResponse { 297 int64 root_view_id = 1; // Echoed from GetParameterDetailsCommand 298 repeated StringEntry strings = 2; 299 Parameter parameter = 3; 300} 301 302message UpdateSettingsCommand { 303 // If true, start (or continue) counting repositions. 304 // If false stop counting recompositions. 305 bool include_recompose_counts = 1; 306 // If true, the recomposition counts will be kept. 307 // If false, the recomposition counts will be reset. 308 bool keep_recompose_counts = 2; 309 // If true, the compose parameters will not be extracted before 310 bool delay_parameter_extractions = 3; 311 // If true, encode nested single children under the top node. 312 bool reduce_child_nesting = 4; 313} 314 315// The active settings after handling of an UpdateSettingsCommand 316message UpdateSettingsResponse { 317 // If true, the agent has the capability for delaying parameter extractions 318 bool can_delay_parameter_extractions = 3; 319} 320 321message Command { 322 oneof specialized { 323 GetComposablesCommand get_composables_command = 1; 324 GetParametersCommand get_parameters_command = 2; 325 GetAllParametersCommand get_all_parameters_command = 3; 326 GetParameterDetailsCommand get_parameter_details_command = 4; 327 UpdateSettingsCommand update_settings_command = 5; 328 } 329} 330 331message Response { 332 oneof specialized { 333 GetComposablesResponse get_composables_response = 1; 334 GetParametersResponse get_parameters_response = 2; 335 GetAllParametersResponse get_all_parameters_response = 3; 336 GetParameterDetailsResponse get_parameter_details_response = 4; 337 UpdateSettingsResponse update_settings_response = 5; 338 339 UnknownCommandResponse unknown_command_response = 100; 340 } 341} 342