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 package com.android.launcher3.util.viewcapture_analysis;
17 
18 import androidx.annotation.NonNull;
19 import androidx.annotation.Nullable;
20 
21 import java.util.HashMap;
22 import java.util.Map;
23 
24 /**
25  * Detector of one kind of anomaly.
26  */
27 abstract class AnomalyDetector {
28     // Index of this detector in ViewCaptureAnalyzer.ANOMALY_DETECTORS
29     public int detectorOrdinal;
30 
31     /**
32      * Element of the tree of ignored nodes.
33      * If the "children" map is empty, then this node should be ignored, i.e. the analysis shouldn't
34      * run for it.
35      * I.e. ignored nodes correspond to the leaves in the ignored nodes tree.
36      */
37     protected static class IgnoreNode {
38         // Map from child node identities to ignore-nodes for these children.
39         public final Map<String, IgnoreNode> children = new HashMap<>();
40     }
41 
42     // Converts the list of full paths of nodes to ignore to a more efficient tree of ignore-nodes.
buildIgnoreNodesTree(Iterable<String> pathsToIgnore)43     protected static IgnoreNode buildIgnoreNodesTree(Iterable<String> pathsToIgnore) {
44         final IgnoreNode root = new IgnoreNode();
45         for (String pathToIgnore : pathsToIgnore) {
46             // Scan the diag path of an ignored node and add its elements into the tree.
47             IgnoreNode currentIgnoreNode = root;
48             for (String part : pathToIgnore.split("\\|")) {
49                 // Ensure that the child of the node is added to the tree.
50                 IgnoreNode child = currentIgnoreNode.children.get(part);
51                 if (child == null) {
52                     currentIgnoreNode.children.put(part, child = new IgnoreNode());
53                 }
54                 currentIgnoreNode = child;
55             }
56         }
57         return root;
58     }
59 
60     /**
61      * Initializes fields of the node that are specific to the anomaly detected by this
62      * detector.
63      */
initializeNode(@onNull ViewCaptureAnalyzer.AnalysisNode info)64     abstract void initializeNode(@NonNull ViewCaptureAnalyzer.AnalysisNode info);
65 
66     /**
67      * Detects anomalies by looking at the last occurrence of a view, and the current one.
68      * null value means that the view. 'oldInfo' and 'newInfo' cannot be both null.
69      * If an anomaly is detected, an exception will be thrown.
70      *
71      * @param oldInfo      the view, as seen in the last frame that contained it in the view
72      *                     hierarchy before 'currentFrame'. 'null' means that the view is first seen
73      *                     in the 'currentFrame'.
74      * @param newInfo      the view in the view hierarchy of the 'currentFrame'. 'null' means that
75      *                     the view is not present in the 'currentFrame', but was present in the
76      *                     previous frame.
77      * @param frameN       number of the current frame.
78      * @param windowSizePx maximum of the window width and height, in pixels.
79      * @return Anomaly diagnostic message if an anomaly has been detected; null otherwise.
80      */
detectAnomalies( @ullable ViewCaptureAnalyzer.AnalysisNode oldInfo, @Nullable ViewCaptureAnalyzer.AnalysisNode newInfo, int frameN, long frameTimeNs, int windowSizePx)81     abstract String detectAnomalies(
82             @Nullable ViewCaptureAnalyzer.AnalysisNode oldInfo,
83             @Nullable ViewCaptureAnalyzer.AnalysisNode newInfo, int frameN,
84             long frameTimeNs, int windowSizePx);
85 }
86