Home | History | Annotate | Download | only in utils
      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      */
     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      */
    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      */
    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