1/*
2 * Copyright (C) 2024 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 {android} from 'protos/transactions/udc/static';
19import {FixedStringFormatter} from 'trace/tree_node/formatters';
20import {Operation} from 'trace/tree_node/operations/operation';
21import {PropertyTreeNode} from 'trace/tree_node/property_tree_node';
22
23export class TranslateChanges implements Operation<PropertyTreeNode> {
24  apply(value: PropertyTreeNode): void {
25    value
26      .getChildByName('transactions')
27      ?.getAllChildren()
28      .forEach((transactionState) => {
29        transactionState
30          .getChildByName('layerChanges')
31          ?.getAllChildren()
32          .forEach((layerState) => {
33            this.translateLayerChanges(layerState);
34          });
35
36        transactionState
37          .getChildByName('displayChanges')
38          ?.getAllChildren()
39          .forEach((displayState) => {
40            this.translateDisplayChanges(displayState);
41          });
42      });
43
44    value
45      .getChildByName('addedDisplays')
46      ?.getAllChildren()
47      .forEach((displayState) => {
48        this.translateDisplayChanges(displayState);
49      });
50  }
51
52  private translateLayerChanges(layerState: PropertyTreeNode) {
53    const what = assertDefined(layerState.getChildByName('what'));
54
55    const originalValue = what.getValue();
56    let translation: string = '';
57
58    if (originalValue.low !== undefined && originalValue.high !== undefined) {
59      translation = this.concatBitsetTokens(
60        this.decodeBitset32(
61          originalValue.low,
62          android.surfaceflinger.proto.LayerState.ChangesLsb,
63        ).concat(
64          this.decodeBitset32(
65            originalValue.high,
66            android.surfaceflinger.proto.LayerState.ChangesMsb,
67          ),
68        ),
69      );
70    } else {
71      const bigintValue = BigInt(originalValue?.toString() ?? 0n);
72      translation = this.concatBitsetTokens(
73        this.decodeBitset32(
74          Number(bigintValue),
75          android.surfaceflinger.proto.LayerState.ChangesLsb,
76        ).concat(
77          this.decodeBitset32(
78            Number(bigintValue >> 32n),
79            android.surfaceflinger.proto.LayerState.ChangesMsb,
80          ),
81        ),
82      );
83    }
84
85    what.setFormatter(new FixedStringFormatter(translation));
86  }
87
88  private translateDisplayChanges(displayState: PropertyTreeNode) {
89    const what = assertDefined(displayState.getChildByName('what'));
90    const originalValue = what.getValue();
91
92    const translation = this.concatBitsetTokens(
93      this.decodeBitset32(
94        Number(originalValue),
95        android.surfaceflinger.proto.DisplayState.Changes,
96      ),
97    );
98
99    what.setFormatter(new FixedStringFormatter(translation));
100  }
101
102  private decodeBitset32(
103    bitset: number,
104    EnumProto: {[key: number]: string},
105  ): string[] {
106    const changes = Object.values(EnumProto)
107      .filter((key) => {
108        if (Number.isNaN(Number(key))) {
109          return false;
110        }
111        return (bitset & Number(key)) !== 0;
112      })
113      .map((key) => EnumProto[Number(key)]);
114    return changes;
115  }
116
117  private concatBitsetTokens(tokens: string[]): string {
118    if (tokens.length === 0) {
119      return '0';
120    }
121    return tokens.join(' | ');
122  }
123}
124