• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.packageinstaller.permission.utils;
18 
19 import android.Manifest;
20 import android.app.AppOpsManager;
21 import android.content.Context;
22 import android.os.SystemProperties;
23 import android.support.annotation.NonNull;
24 import android.util.Log;
25 
26 import com.android.internal.logging.MetricsLogger;
27 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
28 
29 import java.util.Arrays;
30 import java.util.List;
31 
32 /**
33  * For each permission there are four events. The events are in the order of
34  * #ALL_DANGEROUS_PERMISSIONS. The four events per permission are (in that order): "requested",
35  * "granted", "denied", and "revoked".
36  */
37 public class EventLogger {
38     private static final String LOG_TAG = EventLogger.class.getSimpleName();
39 
40     /** All dangerous permission names in the same order as the events in MetricsEvent */
41     private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
42             Manifest.permission.READ_CALENDAR,
43             Manifest.permission.WRITE_CALENDAR,
44             Manifest.permission.CAMERA,
45             Manifest.permission.READ_CONTACTS,
46             Manifest.permission.WRITE_CONTACTS,
47             Manifest.permission.GET_ACCOUNTS,
48             Manifest.permission.ACCESS_FINE_LOCATION,
49             Manifest.permission.ACCESS_COARSE_LOCATION,
50             Manifest.permission.RECORD_AUDIO,
51             Manifest.permission.READ_PHONE_STATE,
52             Manifest.permission.CALL_PHONE,
53             Manifest.permission.READ_CALL_LOG,
54             Manifest.permission.WRITE_CALL_LOG,
55             Manifest.permission.ADD_VOICEMAIL,
56             Manifest.permission.USE_SIP,
57             Manifest.permission.PROCESS_OUTGOING_CALLS,
58             Manifest.permission.READ_CELL_BROADCASTS,
59             Manifest.permission.BODY_SENSORS,
60             Manifest.permission.SEND_SMS,
61             Manifest.permission.RECEIVE_SMS,
62             Manifest.permission.READ_SMS,
63             Manifest.permission.RECEIVE_WAP_PUSH,
64             Manifest.permission.RECEIVE_MMS,
65             Manifest.permission.READ_EXTERNAL_STORAGE,
66             Manifest.permission.WRITE_EXTERNAL_STORAGE,
67             Manifest.permission.READ_PHONE_NUMBERS,
68             Manifest.permission.ANSWER_PHONE_CALLS);
69 
70     private static final List<String> ALL_APPOP_PERMISSIONS = Arrays.asList(
71             Manifest.permission.ACCESS_NOTIFICATIONS,
72             Manifest.permission.SYSTEM_ALERT_WINDOW,
73             Manifest.permission.WRITE_SETTINGS,
74             Manifest.permission.REQUEST_INSTALL_PACKAGES);
75 
76     /**
77      * Get the first event id for the permission.
78      *
79      * <p>There are four events for each permission: <ul>
80      *     <li>Request permission: first id + 0</li>
81      *     <li>Grant permission: first id + 1</li>
82      *     <li>Request for permission denied: first id + 2</li>
83      *     <li>Revoke permission: first id + 3</li>
84      * </ul></p>
85      *
86      * @param name name of the permission
87      *
88      * @return The first event id for the permission
89      */
getBaseEventId(@onNull String name)90     private static int getBaseEventId(@NonNull String name) {
91         int permIndex = ALL_DANGEROUS_PERMISSIONS.indexOf(name);
92 
93         if (permIndex != -1) {
94             return MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR + permIndex * 4;
95         } else {
96             int appOpIndex = ALL_APPOP_PERMISSIONS.indexOf(name);
97 
98             if (appOpIndex != -1) {
99                 return MetricsEvent.ACTION_APPOP_REQUEST_ACCESS_NOTIFICATIONS + appOpIndex * 4;
100             } else {
101                 if (AppOpsManager.permissionToOpCode(name) == AppOpsManager.OP_NONE
102                         || "user".equals(SystemProperties.get("ro.build.type"))) {
103                     Log.i(LOG_TAG, "Unknown permission " + name);
104 
105                     return MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN;
106                 } else {
107                     // Most likely #ALL_DANGEROUS_PERMISSIONS or #ALL_APPOP_PERMISSIONS needs to be
108                     // updated.
109                     //
110                     // Also update
111                     // - metrics_constants.proto
112                     // and most likely:
113                     // - PackageManagerService#ALL_DANGEROUS_PERMISSIONS
114                     throw new IllegalStateException("Unknown permission " + name);
115                 }
116             }
117         }
118     }
119 
120     /**
121      * Log that a permission was requested.
122      *
123      * @param context Context of the caller
124      * @param name name of the permission
125      * @param packageName package permission if for
126      */
logPermissionRequested(@onNull Context context, @NonNull String name, @NonNull String packageName)127     public static void logPermissionRequested(@NonNull Context context, @NonNull String name,
128             @NonNull String packageName) {
129         MetricsLogger.action(context, getBaseEventId(name), packageName);
130     }
131 
132     /**
133      * Log that a permission request was denied.
134      *
135      * @param context Context of the caller
136      * @param name name of the permission
137      * @param packageName package permission if for
138      */
logPermissionDenied(@onNull Context context, @NonNull String name, @NonNull String packageName)139     public static void logPermissionDenied(@NonNull Context context, @NonNull String name,
140             @NonNull String packageName) {
141         MetricsLogger.action(context, getBaseEventId(name) + 2, packageName);
142     }
143 
144 }
145