1 /*
2  * Copyright (C) 2019 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 
17 package com.android.internal.os;
18 
19 import android.metrics.LogMaker;
20 import android.os.Process;
21 
22 import com.android.internal.logging.MetricsLogger;
23 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
24 import com.android.internal.util.FrameworkStatsLog;
25 
26 import dalvik.system.VMRuntime.HiddenApiUsageLogger;
27 
28 class StatsdHiddenApiUsageLogger implements HiddenApiUsageLogger {
29 
30     private final MetricsLogger mMetricsLogger = new MetricsLogger();
31     private static final StatsdHiddenApiUsageLogger sInstance = new StatsdHiddenApiUsageLogger();
32     private int mHiddenApiAccessLogSampleRate = 0;
33     private int mHiddenApiAccessStatslogSampleRate = 0;
34 
setHiddenApiAccessLogSampleRates(int sampleRate, int newSampleRate)35     static void setHiddenApiAccessLogSampleRates(int sampleRate, int newSampleRate) {
36         sInstance.mHiddenApiAccessLogSampleRate = sampleRate;
37         sInstance.mHiddenApiAccessStatslogSampleRate = newSampleRate;
38     }
39 
getInstance()40     static StatsdHiddenApiUsageLogger getInstance() {
41         return StatsdHiddenApiUsageLogger.sInstance;
42     }
43 
hiddenApiUsed(int sampledValue, String packageName, String signature, int accessMethod, boolean accessDenied)44     public void hiddenApiUsed(int sampledValue, String packageName, String signature,
45             int accessMethod, boolean accessDenied) {
46         if (sampledValue < mHiddenApiAccessLogSampleRate) {
47             logUsage(packageName, signature, accessMethod, accessDenied);
48         }
49 
50         if (sampledValue < mHiddenApiAccessStatslogSampleRate) {
51             newLogUsage(signature, accessMethod, accessDenied);
52         }
53     }
54 
logUsage(String packageName, String signature, int accessMethod, boolean accessDenied)55     private void logUsage(String packageName, String signature, int accessMethod,
56             boolean accessDenied) {
57         int accessMethodMetric = HiddenApiUsageLogger.ACCESS_METHOD_NONE;
58         switch(accessMethod) {
59             case HiddenApiUsageLogger.ACCESS_METHOD_NONE:
60                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_NONE;
61                 break;
62             case HiddenApiUsageLogger.ACCESS_METHOD_REFLECTION:
63                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_REFLECTION;
64                 break;
65             case HiddenApiUsageLogger.ACCESS_METHOD_JNI:
66                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_JNI;
67                 break;
68             case HiddenApiUsageLogger.ACCESS_METHOD_LINKING:
69                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_LINKING;
70                 break;
71         }
72 
73         LogMaker logMaker = new LogMaker(MetricsEvent.ACTION_HIDDEN_API_ACCESSED)
74                 .setPackageName(packageName)
75                 .addTaggedData(MetricsEvent.FIELD_HIDDEN_API_SIGNATURE, signature)
76                 .addTaggedData(MetricsEvent.FIELD_HIDDEN_API_ACCESS_METHOD,
77                     accessMethodMetric);
78 
79         if (accessDenied) {
80             logMaker.addTaggedData(MetricsEvent.FIELD_HIDDEN_API_ACCESS_DENIED, 1);
81         }
82 
83         mMetricsLogger.write(logMaker);
84     }
85 
newLogUsage(String signature, int accessMethod, boolean accessDenied)86     private void newLogUsage(String signature, int accessMethod, boolean accessDenied) {
87         int accessMethodProto = FrameworkStatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE;
88         switch(accessMethod) {
89             case HiddenApiUsageLogger.ACCESS_METHOD_NONE:
90                 accessMethodProto = FrameworkStatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE;
91                 break;
92             case HiddenApiUsageLogger.ACCESS_METHOD_REFLECTION:
93                 accessMethodProto = FrameworkStatsLog.HIDDEN_API_USED__ACCESS_METHOD__REFLECTION;
94                 break;
95             case HiddenApiUsageLogger.ACCESS_METHOD_JNI:
96                 accessMethodProto = FrameworkStatsLog.HIDDEN_API_USED__ACCESS_METHOD__JNI;
97                 break;
98             case HiddenApiUsageLogger.ACCESS_METHOD_LINKING:
99                 accessMethodProto = FrameworkStatsLog.HIDDEN_API_USED__ACCESS_METHOD__LINKING;
100                 break;
101         }
102 
103         int uid = Process.myUid();
104         FrameworkStatsLog.write(FrameworkStatsLog.HIDDEN_API_USED, uid, signature,
105                 accessMethodProto, accessDenied);
106     }
107 }
108