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.hoststubgen.filters 17 18 import com.android.hoststubgen.asm.ClassNodes 19 20 /** 21 * Filter that deals with Android specific heuristics. 22 */ 23 class AndroidHeuristicsFilter( 24 private val classes: ClassNodes, 25 val aidlPolicy: FilterPolicyWithReason?, 26 val featureFlagsPolicy: FilterPolicyWithReason?, 27 val syspropsPolicy: FilterPolicyWithReason?, 28 val rFilePolicy: FilterPolicyWithReason?, 29 fallback: OutputFilter 30 ) : DelegatingFilter(fallback) { getPolicyForClassnull31 override fun getPolicyForClass(className: String): FilterPolicyWithReason { 32 if (aidlPolicy != null && classes.isAidlClass(className)) { 33 return aidlPolicy 34 } 35 if (featureFlagsPolicy != null && classes.isFeatureFlagsClass(className)) { 36 return featureFlagsPolicy 37 } 38 if (syspropsPolicy != null && classes.isSyspropsClass(className)) { 39 return syspropsPolicy 40 } 41 if (rFilePolicy != null && classes.isRClass(className)) { 42 return rFilePolicy 43 } 44 return super.getPolicyForClass(className) 45 } 46 } 47 48 /** 49 * @return if a given class "seems like" an AIDL (top-level) class. 50 */ ClassNodesnull51private fun ClassNodes.isAidlClass(className: String): Boolean { 52 return hasClass(className) && 53 hasClass("$className\$Stub") && 54 hasClass("$className\$Stub\$Proxy") 55 } 56 57 /** 58 * Effectively apply @RavenwoodKeepWholeClass to all classes with these names 59 * 60 * @return if a given class "seems like" an feature flags class. 61 */ isFeatureFlagsClassnull62private fun ClassNodes.isFeatureFlagsClass(className: String): Boolean { 63 // Matches template classes defined here: 64 // https://cs.android.com/android/platform/superproject/+/master:build/make/tools/aconfig/templates/ 65 return className.endsWith("/Flags") 66 || className.endsWith("/FeatureFlags") 67 || className.endsWith("/FeatureFlagsImpl") 68 || className.endsWith("/CustomFeatureFlags") 69 || className.endsWith("/FakeFeatureFlagsImpl"); 70 } 71 72 /** 73 * @return if a given class "seems like" a sysprops class. 74 */ ClassNodesnull75private fun ClassNodes.isSyspropsClass(className: String): Boolean { 76 // Matches template classes defined here: 77 // https://cs.android.com/android/platform/superproject/main/+/main:system/tools/sysprop/ 78 return className.startsWith("android/sysprop/") 79 && className.endsWith("Properties") 80 } 81 82 /** 83 * @return if a given class "seems like" an R class or its nested classes. 84 */ isRClassnull85private fun ClassNodes.isRClass(className: String): Boolean { 86 return className.endsWith("/R") || className.contains("/R$") 87 } 88