1/*
2 * Copyright (C) 2023 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 {assertDefined} from 'common/assert_utils';
18import {perfetto} from 'protos/surfaceflinger/latest/static';
19import {android} from 'protos/surfaceflinger/udc/static';
20import {LazyPropertiesStrategyType} from 'trace/tree_node/properties_provider';
21import {PropertyTreeBuilderFromProto} from 'trace/tree_node/property_tree_builder_from_proto';
22import {PropertyTreeNode} from 'trace/tree_node/property_tree_node';
23import {AddCompositionType} from './operations/add_composition_type';
24import {AddDisplayProperties} from './operations/add_display_properties';
25import {AddExcludesCompositionState} from './operations/add_excludes_composition_state';
26import {AddVerboseFlags} from './operations/add_verbose_flags';
27import {UpdateTransforms} from './operations/update_transforms';
28
29export class ParserSfUtils {
30  static readonly EAGER_PROPERTIES = [
31    'id',
32    'name',
33    'type',
34    'parent',
35    'children',
36    'bounds',
37    'transform',
38    'position',
39    'requestedTransform',
40    'requestedPosition',
41    'bufferTransform',
42    'inputWindowInfo',
43    'flags',
44    'z',
45    'cornerRadius',
46    'layerStack',
47    'isOpaque',
48    'activeBuffer',
49    'visibleRegion',
50    'color',
51    'isRelativeOf',
52    'zOrderRelativeOf',
53    'screenBounds',
54    'shadowRadius',
55    'backgroundBlurRadius',
56    'hwcCompositionType',
57  ];
58
59  static readonly DENYLIST_PROPERTIES = [
60    'length',
61    'prototype',
62    'ref',
63    'parent',
64    'timestamp',
65    'layers',
66    'children',
67    'name',
68  ];
69
70  static readonly OPERATIONS = {
71    UpdateTransforms: new UpdateTransforms(),
72    AddVerboseFlags: new AddVerboseFlags(),
73    AddExcludesCompositionStateTrue: new AddExcludesCompositionState(true),
74    AddExcludesCompositionStateFalse: new AddExcludesCompositionState(false),
75    AddDisplayProperties: new AddDisplayProperties(),
76    AddCompositionType: new AddCompositionType(),
77  };
78
79  static makeEagerPropertiesTree(
80    layer: android.surfaceflinger.ILayerProto | perfetto.protos.ILayerProto,
81    duplicateCount: number,
82  ): PropertyTreeNode {
83    const denyList: string[] = [];
84    let obj = layer;
85    do {
86      Object.getOwnPropertyNames(obj).forEach((it) => {
87        if (!ParserSfUtils.EAGER_PROPERTIES.includes(it)) denyList.push(it);
88      });
89      obj = Object.getPrototypeOf(obj);
90    } while (obj);
91
92    return new PropertyTreeBuilderFromProto()
93      .setData(layer)
94      .setRootId(assertDefined(layer.id))
95      .setRootName(assertDefined(layer.name))
96      .setDenyList(denyList)
97      .setDuplicateCount(duplicateCount)
98      .build();
99  }
100
101  static makeEntryEagerPropertiesTree(
102    entry:
103      | android.surfaceflinger.ILayersTraceProto
104      | perfetto.protos.ILayersSnapshotProto,
105  ): PropertyTreeNode {
106    const denyList: string[] = [];
107    let obj = entry;
108    do {
109      Object.getOwnPropertyNames(obj).forEach((it) => {
110        if (it !== 'displays') denyList.push(it);
111      });
112      obj = Object.getPrototypeOf(obj);
113    } while (obj);
114
115    return new PropertyTreeBuilderFromProto()
116      .setData(entry)
117      .setRootId('LayerTraceEntry')
118      .setRootName('root')
119      .setDenyList(denyList)
120      .build();
121  }
122
123  static makeLayerLazyPropertiesStrategy(
124    layer: android.surfaceflinger.ILayerProto | perfetto.protos.ILayerProto,
125    duplicateCount: number,
126  ): LazyPropertiesStrategyType {
127    return async () => {
128      return new PropertyTreeBuilderFromProto()
129        .setData(layer)
130        .setRootId(assertDefined(layer.id))
131        .setRootName(assertDefined(layer.name))
132        .setDenyList(
133          ParserSfUtils.EAGER_PROPERTIES.concat(
134            ParserSfUtils.DENYLIST_PROPERTIES,
135          ),
136        )
137        .setDuplicateCount(duplicateCount)
138        .build();
139    };
140  }
141
142  static makeEntryLazyPropertiesStrategy(
143    entry:
144      | android.surfaceflinger.ILayersTraceProto
145      | perfetto.protos.ILayersSnapshotProto,
146  ): LazyPropertiesStrategyType {
147    return async () => {
148      return new PropertyTreeBuilderFromProto()
149        .setData(entry)
150        .setRootId('LayerTraceEntry')
151        .setRootName('root')
152        .setDenyList(ParserSfUtils.DENYLIST_PROPERTIES)
153        .build();
154    };
155  }
156}
157