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.addNonNullElement 19 import com.android.hoststubgen.asm.ClassNodes 20 import com.android.hoststubgen.asm.toHumanReadableClassName 21 import com.android.hoststubgen.asm.toHumanReadableMethodName 22 import com.android.hoststubgen.log 23 24 // TODO: Validate all input names. 25 26 class InMemoryOutputFilter( 27 private val classes: ClassNodes, 28 fallback: OutputFilter, 29 ) : DelegatingFilter(fallback) { 30 private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf() 31 private val mRenames: MutableMap<String, String> = mutableMapOf() 32 private val mNativeSubstitutionClasses: MutableMap<String, String> = mutableMapOf() 33 private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf() 34 getClassKeynull35 private fun getClassKey(className: String): String { 36 return className.toHumanReadableClassName() 37 } 38 getFieldKeynull39 private fun getFieldKey(className: String, fieldName: String): String { 40 return getClassKey(className) + "." + fieldName 41 } 42 getMethodKeynull43 private fun getMethodKey(className: String, methodName: String, signature: String): String { 44 return getClassKey(className) + "." + methodName + ";" + signature 45 } 46 getPolicyForClassnull47 override fun getPolicyForClass(className: String): FilterPolicyWithReason { 48 return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className) 49 } 50 checkClassnull51 private fun checkClass(className: String) { 52 if (classes.findClass(className) == null) { 53 log.w("Unknown class $className") 54 } 55 } 56 checkFieldnull57 private fun checkField(className: String, fieldName: String) { 58 if (classes.findField(className, fieldName) == null) { 59 log.w("Unknown field $className.$fieldName") 60 } 61 } 62 checkMethodnull63 private fun checkMethod( 64 className: String, 65 methodName: String, 66 descriptor: String 67 ) { 68 if (classes.findMethod(className, methodName, descriptor) == null) { 69 log.w("Unknown method $className.$methodName$descriptor") 70 } 71 } 72 setPolicyForClassnull73 fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) { 74 checkClass(className) 75 mPolicies[getClassKey(className)] = policy 76 } 77 getPolicyForFieldnull78 override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason { 79 return mPolicies[getFieldKey(className, fieldName)] 80 ?: super.getPolicyForField(className, fieldName) 81 } 82 setPolicyForFieldnull83 fun setPolicyForField(className: String, fieldName: String, policy: FilterPolicyWithReason) { 84 checkField(className, fieldName) 85 mPolicies[getFieldKey(className, fieldName)] = policy 86 } 87 getPolicyForMethodnull88 override fun getPolicyForMethod( 89 className: String, 90 methodName: String, 91 descriptor: String, 92 ): FilterPolicyWithReason { 93 return mPolicies[getMethodKey(className, methodName, descriptor)] 94 ?: super.getPolicyForMethod(className, methodName, descriptor) 95 } 96 setPolicyForMethodnull97 fun setPolicyForMethod( 98 className: String, 99 methodName: String, 100 descriptor: String, 101 policy: FilterPolicyWithReason, 102 ) { 103 checkMethod(className, methodName, descriptor) 104 mPolicies[getMethodKey(className, methodName, descriptor)] = policy 105 } 106 getRenameTonull107 override fun getRenameTo(className: String, methodName: String, descriptor: String): String? { 108 return mRenames[getMethodKey(className, methodName, descriptor)] 109 ?: super.getRenameTo(className, methodName, descriptor) 110 } 111 setRenameTonull112 fun setRenameTo(className: String, methodName: String, descriptor: String, toName: String) { 113 checkMethod(className, methodName, descriptor) 114 checkMethod(className, toName, descriptor) 115 mRenames[getMethodKey(className, methodName, descriptor)] = toName 116 } 117 getNativeSubstitutionClassnull118 override fun getNativeSubstitutionClass(className: String): String? { 119 return mNativeSubstitutionClasses[getClassKey(className)] 120 ?: super.getNativeSubstitutionClass(className) 121 } 122 setNativeSubstitutionClassnull123 fun setNativeSubstitutionClass(from: String, to: String) { 124 checkClass(from) 125 126 // Native substitute classes may be provided from other jars, so we can't do this check. 127 // ensureClassExists(to) 128 mNativeSubstitutionClasses[getClassKey(from)] = to.toHumanReadableClassName() 129 } 130 getClassLoadHooksnull131 override fun getClassLoadHooks(className: String): List<String> { 132 return addNonNullElement(super.getClassLoadHooks(className), 133 mClassLoadHooks[getClassKey(className)]) 134 } 135 setClassLoadHooknull136 fun setClassLoadHook(className: String, methodName: String) { 137 mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName() 138 } 139 }