Loading tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt +1 −1 Original line number Diff line number Diff line Loading @@ -158,7 +158,7 @@ class HostStubGen(val options: HostStubGenOptions) { // This is used when a member (methods, fields, nested classes) don't get any polices // from upper filters. e.g. when a method has no annotations, then this filter will apply // the class-wide policy, if any. (if not, we'll fall back to the above filter.) filter = ClassWidePolicyPropagatingFilter(filter) filter = ClassWidePolicyPropagatingFilter(allClasses, filter) // Inject default hooks from options. filter = DefaultHookInjectingFilter( Loading tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt +1 −1 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ fun isAnonymousInnerClass(cn: ClassNode): Boolean { * Otherwise, return null. */ fun getDirectOuterClassName(className: String): String? { val pos = className.indexOf('$') val pos = className.lastIndexOf('$') if (pos < 0) { return null } Loading tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt +26 −9 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.hoststubgen.filters import com.android.hoststubgen.asm.ClassNodes import com.android.hoststubgen.asm.getDirectOuterClassName /** Loading @@ -22,24 +23,40 @@ import com.android.hoststubgen.asm.getDirectOuterClassName * (obtained from [outermostFilter]) to the fields and methods. */ class ClassWidePolicyPropagatingFilter( private val classes: ClassNodes, fallback: OutputFilter, ) : DelegatingFilter(fallback) { private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? { var currentClass = className // If the class name is `a.b.c.A$B$C`, then we try to get the class wide policy // from a.b.c.A$B$C, then a.b.c.A$B, and then a.b.c.A. while (true) { // Sometimes a class name has a `$` in it but not as a nest class name separator -- // e.g. class name like "MyClass$$". In this case, `MyClass$` may not actually be // a class name. // So before getting the class policy on a nonexistent class, which may cause an // incorrect result, we make sure if className actually exists. if (classes.hasClass(className)) { outermostFilter.getPolicyForClass(className).let { policy -> if (policy.policy.isClassWidePolicy) { val p = if (resolve) policy.policy.resolveClassWidePolicy() else policy.policy val p = if (resolve) { policy.policy.resolveClassWidePolicy() } else { policy.policy } return p.withReason(policy.reason).wrapReason("class-wide in $currentClass") return p.withReason(policy.reason) .wrapReason("class-wide in $currentClass") } // If the class's policy is remove, then remove it. if (policy.policy == FilterPolicy.Remove) { return FilterPolicy.Remove.withReason("class-wide in $currentClass") } } } // Next, look at the outer class... val outer = getDirectOuterClassName(currentClass) Loading tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/AsmUtilsTest.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.hoststubgen.utils import com.android.hoststubgen.asm.getDirectOuterClassName import com.google.common.truth.Truth.assertThat import org.junit.Test class AsmUtilsTest { private fun checkGetDirectOuterClassName(input: String, expected: String?) { assertThat(getDirectOuterClassName(input)).isEqualTo(expected) } @Test fun testGetDirectOuterClassName() { checkGetDirectOuterClassName("a", null) checkGetDirectOuterClassName("a\$x", "a") checkGetDirectOuterClassName("a.b.c\$x", "a.b.c") checkGetDirectOuterClassName("a.b.c\$x\$y", "a.b.c\$x") } } No newline at end of file Loading
tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt +1 −1 Original line number Diff line number Diff line Loading @@ -158,7 +158,7 @@ class HostStubGen(val options: HostStubGenOptions) { // This is used when a member (methods, fields, nested classes) don't get any polices // from upper filters. e.g. when a method has no annotations, then this filter will apply // the class-wide policy, if any. (if not, we'll fall back to the above filter.) filter = ClassWidePolicyPropagatingFilter(filter) filter = ClassWidePolicyPropagatingFilter(allClasses, filter) // Inject default hooks from options. filter = DefaultHookInjectingFilter( Loading
tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt +1 −1 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ fun isAnonymousInnerClass(cn: ClassNode): Boolean { * Otherwise, return null. */ fun getDirectOuterClassName(className: String): String? { val pos = className.indexOf('$') val pos = className.lastIndexOf('$') if (pos < 0) { return null } Loading
tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt +26 −9 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.hoststubgen.filters import com.android.hoststubgen.asm.ClassNodes import com.android.hoststubgen.asm.getDirectOuterClassName /** Loading @@ -22,24 +23,40 @@ import com.android.hoststubgen.asm.getDirectOuterClassName * (obtained from [outermostFilter]) to the fields and methods. */ class ClassWidePolicyPropagatingFilter( private val classes: ClassNodes, fallback: OutputFilter, ) : DelegatingFilter(fallback) { private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? { var currentClass = className // If the class name is `a.b.c.A$B$C`, then we try to get the class wide policy // from a.b.c.A$B$C, then a.b.c.A$B, and then a.b.c.A. while (true) { // Sometimes a class name has a `$` in it but not as a nest class name separator -- // e.g. class name like "MyClass$$". In this case, `MyClass$` may not actually be // a class name. // So before getting the class policy on a nonexistent class, which may cause an // incorrect result, we make sure if className actually exists. if (classes.hasClass(className)) { outermostFilter.getPolicyForClass(className).let { policy -> if (policy.policy.isClassWidePolicy) { val p = if (resolve) policy.policy.resolveClassWidePolicy() else policy.policy val p = if (resolve) { policy.policy.resolveClassWidePolicy() } else { policy.policy } return p.withReason(policy.reason).wrapReason("class-wide in $currentClass") return p.withReason(policy.reason) .wrapReason("class-wide in $currentClass") } // If the class's policy is remove, then remove it. if (policy.policy == FilterPolicy.Remove) { return FilterPolicy.Remove.withReason("class-wide in $currentClass") } } } // Next, look at the outer class... val outer = getDirectOuterClassName(currentClass) Loading
tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/AsmUtilsTest.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.hoststubgen.utils import com.android.hoststubgen.asm.getDirectOuterClassName import com.google.common.truth.Truth.assertThat import org.junit.Test class AsmUtilsTest { private fun checkGetDirectOuterClassName(input: String, expected: String?) { assertThat(getDirectOuterClassName(input)).isEqualTo(expected) } @Test fun testGetDirectOuterClassName() { checkGetDirectOuterClassName("a", null) checkGetDirectOuterClassName("a\$x", "a") checkGetDirectOuterClassName("a.b.c\$x", "a.b.c") checkGetDirectOuterClassName("a.b.c\$x\$y", "a.b.c\$x") } } No newline at end of file