1 /* 2 * Copyright (C) 2024 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.permissioncontroller.ecm 18 19 import android.annotation.SuppressLint 20 import android.app.AppOpsManager 21 import android.app.ecm.EnhancedConfirmationManager 22 import android.content.Context 23 import android.content.pm.PackageManager 24 import android.os.UserHandle 25 import android.permission.flags.Flags 26 import android.util.Log 27 import com.android.modules.utils.build.SdkLevel 28 import com.android.permissioncontroller.PermissionControllerStatsLog 29 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_CANCELLED 30 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_LEARN_MORE 31 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_OK 32 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_SUPPRESSED 33 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_UNSPECIFIED 34 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_APPOP 35 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_OTHER 36 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_PERMISSION 37 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_ROLE 38 import com.android.permissioncontroller.PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_UNSPECIFIED 39 import com.android.permissioncontroller.permission.utils.Utils 40 41 /** 42 * Provides ECM-related metrics logging for PermissionController. 43 * 44 * @hide 45 */ 46 object EnhancedConfirmationStatsLogUtils { 47 private val LOG_TAG = EnhancedConfirmationStatsLogUtils::class.java.simpleName 48 49 enum class DialogResult(val statsLogValue: Int) { 50 Unspecified(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_UNSPECIFIED), 51 Cancelled(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_CANCELLED), 52 LearnMore(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_LEARN_MORE), 53 Okay(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_OK), 54 Suppressed(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__RESULT__RESULT_SUPPRESSED) 55 } 56 57 enum class SettingType(val statsLogValue: Int) { 58 Unspecified( 59 ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_UNSPECIFIED 60 ), 61 Appop(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_APPOP), 62 Permission( 63 ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_PERMISSION 64 ), 65 Role(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_ROLE), 66 Other(ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED__SETTING_TYPE__SETTING_TYPE_OTHER); 67 68 companion object { fromIdentifiernull69 fun fromIdentifier(settingIdentifier: String): SettingType = 70 when { 71 settingIdentifier.startsWith("android:") -> Appop 72 settingIdentifier.startsWith("android.permission.") -> Permission 73 settingIdentifier.startsWith("android.permission-group.") -> Permission 74 settingIdentifier.startsWith("android.app.role.") -> Role 75 else -> Other 76 } 77 } 78 } 79 logDialogResultReportednull80 fun logDialogResultReported( 81 uid: Int, 82 settingIdentifier: String, 83 firstShowForApp: Boolean, 84 dialogResult: DialogResult 85 ) { 86 if (!SdkLevel.isAtLeastV() || !Flags.enhancedConfirmationModeApisEnabled()) { 87 return 88 } 89 val settingType = SettingType.fromIdentifier(settingIdentifier) 90 91 Log.v( 92 LOG_TAG, 93 "ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED: " + 94 "uid='$uid', " + 95 "settingIdentifier='$settingIdentifier', " + 96 "firstShowForApp='$firstShowForApp', " + 97 "settingType='$settingType', " + 98 "result='${dialogResult.statsLogValue}'" 99 ) 100 101 PermissionControllerStatsLog.write( 102 PermissionControllerStatsLog.ENHANCED_CONFIRMATION_DIALOG_RESULT_REPORTED, 103 uid, 104 settingIdentifier, 105 firstShowForApp, 106 settingType.statsLogValue, 107 dialogResult.statsLogValue 108 ) 109 } 110 111 @SuppressLint("MissingPermission") isPackageEcmRestrictednull112 fun isPackageEcmRestricted(context: Context, packageName: String, uid: Int): Boolean { 113 if (!SdkLevel.isAtLeastV() || !Flags.enhancedConfirmationModeApisEnabled()) { 114 return false 115 } 116 val userContext = Utils.getUserContext(context, UserHandle.getUserHandleForUid(uid)) 117 val ecm = userContext.getSystemService(EnhancedConfirmationManager::class.java) 118 return try { 119 val arbitrarilyChosenRestrictedSetting = AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE 120 ecm?.isRestricted(packageName, arbitrarilyChosenRestrictedSetting) ?: false 121 } catch (e: PackageManager.NameNotFoundException) { 122 false 123 } 124 } 125 } 126