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 import android.util.StatsLog;
22 
23 import com.android.internal.logging.MetricsLogger;
24 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
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         if (sampleRate != -1) {
37             sInstance.mHiddenApiAccessLogSampleRate = sampleRate;
38         }
39         if (newSampleRate != -1) {
40             sInstance.mHiddenApiAccessStatslogSampleRate = newSampleRate;
41         }
42     }
43 
getInstance()44     static StatsdHiddenApiUsageLogger getInstance() {
45         return StatsdHiddenApiUsageLogger.sInstance;
46     }
47 
hiddenApiUsed(int sampledValue, String packageName, String signature, int accessMethod, boolean accessDenied)48     public void hiddenApiUsed(int sampledValue, String packageName, String signature,
49             int accessMethod, boolean accessDenied) {
50         if (sampledValue < mHiddenApiAccessLogSampleRate) {
51             logUsage(packageName, signature, accessMethod, accessDenied);
52         }
53 
54         if (sampledValue < mHiddenApiAccessStatslogSampleRate) {
55             newLogUsage(signature, accessMethod, accessDenied);
56         }
57     }
58 
logUsage(String packageName, String signature, int accessMethod, boolean accessDenied)59     private void logUsage(String packageName, String signature, int accessMethod,
60             boolean accessDenied) {
61         int accessMethodMetric = HiddenApiUsageLogger.ACCESS_METHOD_NONE;
62         switch(accessMethod) {
63             case HiddenApiUsageLogger.ACCESS_METHOD_NONE:
64                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_NONE;
65                 break;
66             case HiddenApiUsageLogger.ACCESS_METHOD_REFLECTION:
67                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_REFLECTION;
68                 break;
69             case HiddenApiUsageLogger.ACCESS_METHOD_JNI:
70                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_JNI;
71                 break;
72             case HiddenApiUsageLogger.ACCESS_METHOD_LINKING:
73                 accessMethodMetric = MetricsEvent.ACCESS_METHOD_LINKING;
74                 break;
75         }
76 
77         LogMaker logMaker = new LogMaker(MetricsEvent.ACTION_HIDDEN_API_ACCESSED)
78                 .setPackageName(packageName)
79                 .addTaggedData(MetricsEvent.FIELD_HIDDEN_API_SIGNATURE, signature)
80                 .addTaggedData(MetricsEvent.FIELD_HIDDEN_API_ACCESS_METHOD,
81                     accessMethodMetric);
82 
83         if (accessDenied) {
84             logMaker.addTaggedData(MetricsEvent.FIELD_HIDDEN_API_ACCESS_DENIED, 1);
85         }
86 
87         mMetricsLogger.write(logMaker);
88     }
89 
newLogUsage(String signature, int accessMethod, boolean accessDenied)90     private void newLogUsage(String signature, int accessMethod, boolean accessDenied) {
91         int accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE;
92         switch(accessMethod) {
93             case HiddenApiUsageLogger.ACCESS_METHOD_NONE:
94                 accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE;
95                 break;
96             case HiddenApiUsageLogger.ACCESS_METHOD_REFLECTION:
97                 accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__REFLECTION;
98                 break;
99             case HiddenApiUsageLogger.ACCESS_METHOD_JNI:
100                 accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__JNI;
101                 break;
102             case HiddenApiUsageLogger.ACCESS_METHOD_LINKING:
103                 accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__LINKING;
104                 break;
105         }
106 
107         int uid = Process.myUid();
108         StatsLog.write(StatsLog.HIDDEN_API_USED, uid, signature, accessMethodProto, accessDenied);
109     }
110 }
111