1 /*
<lambda>null2  * Copyright (C) 2024 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
17 
18 import com.android.hoststubgen.asm.getOuterClassNameFromFullClassName
19 import com.android.hoststubgen.asm.getPackageNameFromFullClassName
20 import com.android.hoststubgen.filters.FilterPolicyWithReason
21 import org.objectweb.asm.Opcodes
22 import java.io.PrintWriter
23 
24 open class HostStubGenStats {
25     data class Stats(
26             var supported: Int = 0,
27             var total: Int = 0,
28             val children: MutableMap<String, Stats> = mutableMapOf<String, Stats>(),
29     )
30 
31     private val stats = mutableMapOf<String, Stats>()
32 
33     data class Api(
34         val fullClassName: String,
35         val methodName: String,
36         val methodDesc: String,
37     )
38 
39     private val apis = mutableListOf<Api>()
40 
41     fun onVisitPolicyForMethod(
42         fullClassName: String,
43         methodName: String,
44         descriptor: String,
45         policy: FilterPolicyWithReason,
46         access: Int
47     ) {
48         if (policy.policy.isSupported) {
49             apis.add(Api(fullClassName, methodName, descriptor))
50         }
51 
52         // Ignore methods that aren't public
53         if ((access and Opcodes.ACC_PUBLIC) == 0) return
54         // Ignore methods that are abstract
55         if ((access and Opcodes.ACC_ABSTRACT) != 0) return
56         // Ignore methods where policy isn't relevant
57         if (policy.isIgnoredForStats) return
58 
59         val packageName = getPackageNameFromFullClassName(fullClassName)
60         val className = getOuterClassNameFromFullClassName(fullClassName)
61 
62         // Ignore methods for certain generated code
63         if (className.endsWith("Proto")
64                 or className.endsWith("ProtoEnums")
65                 or className.endsWith("LogTags")
66                 or className.endsWith("StatsLog")) {
67             return
68         }
69 
70         val packageStats = stats.getOrPut(packageName) { Stats() }
71         val classStats = packageStats.children.getOrPut(className) { Stats() }
72 
73         if (policy.policy.isSupported) {
74             packageStats.supported += 1
75             classStats.supported += 1
76         }
77         packageStats.total += 1
78         classStats.total += 1
79     }
80 
81     fun dumpOverview(pw: PrintWriter) {
82         pw.printf("PackageName,ClassName,SupportedMethods,TotalMethods\n")
83         stats.toSortedMap().forEach { (packageName, packageStats) ->
84             if (packageStats.supported > 0) {
85                 packageStats.children.toSortedMap().forEach { (className, classStats) ->
86                     pw.printf("%s,%s,%d,%d\n", packageName, className,
87                             classStats.supported, classStats.total)
88                 }
89             }
90         }
91     }
92 }
93