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