/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.packageinstaller.permission.utils; import android.Manifest; import android.app.AppOpsManager; import android.content.Context; import android.os.SystemProperties; import android.support.annotation.NonNull; import android.util.Log; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import java.util.Arrays; import java.util.List; /** * For each permission there are four events. The events are in the order of * #ALL_DANGEROUS_PERMISSIONS. The four events per permission are (in that order): "requested", * "granted", "denied", and "revoked". */ public class EventLogger { private static final String LOG_TAG = EventLogger.class.getSimpleName(); /** All dangerous permission names in the same order as the events in MetricsEvent */ private static final List ALL_DANGEROUS_PERMISSIONS = Arrays.asList( Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR, Manifest.permission.CAMERA, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS, Manifest.permission.GET_ACCOUNTS, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_PHONE_STATE, Manifest.permission.CALL_PHONE, Manifest.permission.READ_CALL_LOG, Manifest.permission.WRITE_CALL_LOG, Manifest.permission.ADD_VOICEMAIL, Manifest.permission.USE_SIP, Manifest.permission.PROCESS_OUTGOING_CALLS, Manifest.permission.READ_CELL_BROADCASTS, Manifest.permission.BODY_SENSORS, Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_WAP_PUSH, Manifest.permission.RECEIVE_MMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_NUMBERS, Manifest.permission.ANSWER_PHONE_CALLS); private static final List ALL_APPOP_PERMISSIONS = Arrays.asList( Manifest.permission.ACCESS_NOTIFICATIONS, Manifest.permission.SYSTEM_ALERT_WINDOW, Manifest.permission.WRITE_SETTINGS, Manifest.permission.REQUEST_INSTALL_PACKAGES); /** * Get the first event id for the permission. * *

There are four events for each permission:

* * @param name name of the permission * * @return The first event id for the permission */ private static int getBaseEventId(@NonNull String name) { int permIndex = ALL_DANGEROUS_PERMISSIONS.indexOf(name); if (permIndex != -1) { return MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR + permIndex * 4; } else { int appOpIndex = ALL_APPOP_PERMISSIONS.indexOf(name); if (appOpIndex != -1) { return MetricsEvent.ACTION_APPOP_REQUEST_ACCESS_NOTIFICATIONS + appOpIndex * 4; } else { if (AppOpsManager.permissionToOpCode(name) == AppOpsManager.OP_NONE || "user".equals(SystemProperties.get("ro.build.type"))) { Log.i(LOG_TAG, "Unknown permission " + name); return MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN; } else { // Most likely #ALL_DANGEROUS_PERMISSIONS or #ALL_APPOP_PERMISSIONS needs to be // updated. // // Also update // - metrics_constants.proto // and most likely: // - PackageManagerService#ALL_DANGEROUS_PERMISSIONS throw new IllegalStateException("Unknown permission " + name); } } } } /** * Log that a permission was requested. * * @param context Context of the caller * @param name name of the permission * @param packageName package permission if for */ public static void logPermissionRequested(@NonNull Context context, @NonNull String name, @NonNull String packageName) { MetricsLogger.action(context, getBaseEventId(name), packageName); } /** * Log that a permission request was denied. * * @param context Context of the caller * @param name name of the permission * @param packageName package permission if for */ public static void logPermissionDenied(@NonNull Context context, @NonNull String name, @NonNull String packageName) { MetricsLogger.action(context, getBaseEventId(name) + 2, packageName); } }